mutex

section simultan ten

基本概述

Mutex:/mjuteks/
互斥(體) 又稱同步基元使用了System.Threading 命名空間。
當創建一個應用程式類時,將同時創建一個系統範圍內的命名的Mutex對象。這個互斥元在整個作業系統中都是可見的。當已經存在一個同名的互斥元時,構造函式將會輸出一個布爾值。程式代碼通過檢測這個布爾值來判斷指定的程式實例是否啟動,如果已經存在同名互斥元的話,則顯示一個對話框,告知用戶應用程式已經啟動,並退出應用程式。
A data structure for mutual exclusion, also known as a binary semaphore. A mutex is basically just a multitasking-aware binary flag that can be used to synchronize the activities of multiple tasks. As such, it can be used to protect critical sections of the code from interruption and shared resources from simultaneous use.
表現互斥現象的數據結構,也被當作二元信號燈。一個互斥基本上是一個多任務敏感的二元信號,它能用作同步多任務的行為,它常用作保護從中斷來的臨界段代碼並且在共享同步使用的資源。

mutex

場景

Mutex主要用於有大量並發訪問並存在cache過期的場合,如
首頁top 10, 由資料庫載入到memcache快取n分鐘微博中名人的content cache, 一旦不存在會大量請求不能命中並載入資料庫需要執行多個IO操作生成的數據存在cache中, 比如查詢db多次

問題

在大並發的場合,當cache失效時,大量並發同時取不到cache,會同一瞬間去訪問db並回設cache,可能會給系統帶來潛在的超負荷風險。我們曾經線上上系統出現過類似故障

解決方法

方法一
在load db之前先add一個mutex key, mutex key add成功之後再去做載入db, 如果add失敗則sleep之後重試讀取原cache數據。為了防止死鎖,mutex key也需要設定過期時間。偽代碼如下
(註:下文偽代碼僅供了解思路,可能存在bug,歡迎隨時指出。)
if (memcache.get(key) == null)
{ // 3 min timeout to avoid mutex holder crash
if (memcache.add(key_mutex, 3 * 60 * 1000) == true)
{ value = db.get(key);
memcache.set(key, value);
memcache.delete(key_mutex);
} else
{ sleep(50);
retry();
}
}
方法二
在value內部設定1個逾時值(timeout1), timeout1比實際的memcache timeout(timeout2)小。當從cache讀取到timeout1發現它已經過期時候,馬上延長timeout1並重新設定到cache。然後再從資料庫載入數據並設定到cache中。偽代碼如下
v = memcache.get(key);
if (v == null)
{ if (memcache.add(key_mutex, 3 * 60 * 1000) == true)
{ value = db.get(key);
memcache.set(key, value);
memcache.delete(key_mutex);
} else
{ sleep(50);
retry();
}
} else
{ if (v.timeout <= now())
{ if (memcache.add(key_mutex, 3 * 60 * 1000) == true)
{ // extend the timeout for other threads
v.timeout += 3 * 60 * 1000;
memcache.set(key, v, KEY_TIMEOUT * 2);
// load the latest value from db v = db.get(key);
v.timeout = KEY_TIMEOUT;
memcache.set(key, value, KEY_TIMEOUT * 2);
memcache.delete(key_mutex);
} else
{ sleep(50);
retry();
}
}
}
相對於方案一
優點:避免cache失效時刻大量請求獲取不到mutex並進行sleep
缺點:代碼複雜性增大,因此一般場合用方案一也已經足夠。
方案二在Memcached FAQ中也有詳細介紹 How to prevent clobbering updates, stampeding requests,並且Brad還介紹了用他另外一個得意的工具 Gearman 來實現單實例設定cache的方法,見 Cache miss stampedes,不過用Gearman來解決就感覺就有點奇技淫巧了。

相關詞條

相關搜尋

熱門詞條

聯絡我們