在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(); } }