在key-value系统中缓存了网络服务器上一个重要的ticket,这个ticket用来受权。在必定的时间周期7200s里更新。现须要实现一个CGI提供给前端获取这个ticket,CGI访问量为天天百万pv左右。html
假设某一时刻ticket要过时时有A,B两个请求。A请求过来发现ticket过时,开始从网络服务器上获取最新的ticket并写入KV,同时服务器更新本身存储的ticket。而B刚好在A写入前读出了ticket,此时服务器上的ticket和A同步了。但B的ticket是过时的,这会致使用B获取的ticket去请求资源时失败。前端
于是须要读写分离。其实读写分离也意味着把并发锁转移,从可能几K个并发争锁减小到几个并发争锁。同时在CGI中下降了加锁成本。缓存
思路以下:服务器
往KV里添加一个字段daemon_mutex
,对应的value为pid + timestamp
。网络
daemon可能会挂掉。挂掉会致使两方面问题并发
所以能够启动三个daemon进程,相互监督。.net
步骤以下:code
daemon_mutex
的timestamp字段,至关于心跳数据。每隔15分钟更新KV中的ticket。(ticket更新不用太频繁)daemon_mutex
的timestamp字段,若time(NULL) - kv.update_time() > 15
说明主进程挂掉了,2个从进程开始争锁,抢到的进程升级为主进程。重复以上。memcache也能够利用add
去实现并发锁,主要是经过add的原子性来判断是否要执行关键代码。htm
if (memcache.get(key) == null) { // 设置过时时间防止持有写锁的进程死锁 if (memcache.add(key_mutex, 3 * 60 * 1000) == true) { //主进程执行流,当能够增长key_mutex字段,说明得到锁 //业务逻辑操做 value = db.get(key); memcache.set(key, value); //删除key_mutex memcache.delete(key_mutex); } else { //从进程执行流 sleep(50); retry(); } }