Jump to content

Manual:内存缓存

本頁使用了標題或全文手工轉換
From mediawiki.org
This page is a translated version of the page Manual:Memcached and the translation is 100% complete.

memcached是一種記憶體內部的物件型儲存空間,MediaWiki可用於快取值,以減少執行耗費資源的運算需求、並降低資料庫的伺服器的負載。

何時使用

對於由單一伺服器所代管的小型網站而言,安裝Memcached可能並不值得費心去做。 對於這樣的情況,請考慮將MediaWiki設定為改用PHP的APCu作為主要的物件型儲存空間。 對於維基百科這類的大型網站、以及一般是由多台網頁伺服器代管的維基系統,Memcached是MediaWiki物件快取常見的選擇。

有關MediaWiki快取選項的更多資訊,請參閱手冊:效能調校§物件快取

安装Memcached

大多數適用於 Linux 和 macOS 的套件管理程式皆提供可直接使用的 Memcached 套件(包含 Debian、Fedora 及 Ubuntu 系統)。

若您的發行版沒有現成可用的套件,您可能需要從原始碼去編譯,請至memcached.org下載原始碼。 要從原始碼編譯,您還需要libevent。 Memcached與libevent皆為採用BSD型式的授權條款所發佈的開源專案。

更多關於Memcached的資訊,請參閱維基百科上的「Memcached」條目。

安全性

Memcached 無任何安全性防護或驗證機制。 請確保您的伺服器已設置適當的防火牆,且用於memcached伺服器的通訊埠不得對外開放公開存取。 否則,任何網路上的使用者都能將資料寫入您的快取、或是從中讀取資料。

某個熟悉 MediaWiki 內部運作的攻擊者可藉此取得開發者權限,他不僅能刪除維基資料庫中的所有資料,還能取得所有使用者的密碼哈希值與電子郵件地址。

Memcached的PHP客戶端

截至本文(MediaWiki 1.27)撰寫時,MediaWiki使用純PHP編寫的 memcached 客戶端(基於Ryan T. Dean的工作成果)。 它也支持php-memcachedPECL擴充功能。 要在 MediaWiki 中使用 Memcached,PHP 必須以 --enable-sockets 選項編譯(此為預設值)。

若欲使用PECL 基礎memcached客戶端,請將 $wgMainCacheType 及相關的快取變數設定為 'memcached-pecl' 而非 CACHE_MEMCACHED。此 PECL memcached 客戶端支援若干附加功能,例如 SASL 授權與連線池化,其對部份的使用者可能有所助益。

若要進一步瞭解如何為MediaWiki的不同部份選擇Memcached作為後端,請參閱Manual:Caching

设置

若您想從小規模開始,只需在您的網頁伺服器上運行一個 Memcached:

 memcached -d -l 127.0.0.1 -p 11211 -m 64

(以常駐模式運行,僅可透過環回介面存取,使用端口 11211,最多佔用 64MB 記憶體)

請在您的LocalSettings.php檔案中設定:

$wgMainCacheType = CACHE_MEMCACHED;
$wgParserCacheType = CACHE_MEMCACHED; // 非必填
$wgMessageCacheType = CACHE_MEMCACHED; // 非必填
$wgMemCachedServers = [ '127.0.0.1:11211' ];

$wgSessionsInObjectCache = true; // 非必填--已在1.33版以上移除
$wgSessionCacheType = CACHE_MEMCACHED; // 非必填

那時該維基應就會使用 memcached 來快取各種資料。 若要使用多台伺服器(多台實體分離的箱型設備、或在單台大型記憶體x86/Power箱型設備的機器上的多個快取),只需將更多項目加入陣列即可。 若要增加某台伺服器的權重(例如因其記憶體容量是其他伺服器的兩倍,而您希望平均分配使用量),請將該伺服器的入口設為子陣列:

$wgMemCachedServers = [
    '127.0.0.1:11211', // 這個箱型設備裡有1GB
    [ '192.168.0.1:11211', 2 ] // 其他箱型設備裡有2GB
];

SELinux

對於SELinux的系統,Memcached 提供多種安全策略選項。 要讓 Apache (httpd) 能存取 Memcached,您必須設定以下的政策:

 setsebool -P httpd_can_network_memcache 1

故障排除

儲存過程中的工作階段資料損失

若您將工作階段資料儲存於 memcached 中,且使用者在嘗試儲存編輯內容時會間歇性地看到此訊息:

对不起!由于会话数据丢失,我们无法处理您的编辑。

您可能已经退出。请核实您是否仍在登录,并重试。 如果仍然不能工作,尝试退出并重新登录,并检查您的浏览器是否允许来自该网站的cookie。

那麼您的其中一台或多台memcached伺服器可能存在組態錯誤的 /etc/hosts 檔案。 在每台的Memcached伺服器上,請確保該伺服器自身的主機名稱已映射至localhost:

127.0.0.1  servername.here localhost localhost.localdomain ...

否則,伺服器可能無法連接到其自身的memcached进程。

在程式碼中使用memcached

若您正在編寫一個執行很耗時的資料庫查詢的擴充功能,將資料快取至memcached可能會有助益。 取得memcached的句柄主要有以下幾種方式:

  • $cache = ObjectCache::getMainWANInstance()
    
    …若您需要一個基於記憶體的共享快取,其具備有明確清除能力,用以儲存來自持久性來源的衍生值,就用上面這個
  • $cache = ObjectCache::getLocalClusterInstance()
    
    …若您需要一個基於記憶體、短暫性的儲存空間,該儲存空間不會在資料中心之間共享,就用上面這個
  • $cache = ObjectCache::getLocalServerInstance()
    
    …若您需要一個基於記憶體、短暫性的快取,該快取不會在網頁伺服器之間共享,就用上面這個
  • $cache = wfGetCache( CACHE_ANYTHING )
    
    …若您需要任何可用的快取,其無論是否是資料中心專屬,甚至可以是一個使用SQL資料庫所模擬出來的快取,就用上面這個。 請注意,這些方法可能回傳與Redis、APC、MySQL、或其他儲存系統通訊的句柄。 「memcached」一詞有其歷史淵源,源自其API是圍繞在memcached有支援的簡易指令所定義的,以及,迄今為止,memcached通常仍是最佳的通用型快取儲存方案的此一事實。

具有特定需求(例如持久性)的擴充功能應定義新的組態設定,像是$wgMyExtCache$wgMyExtWANCache。 使用快取的程式碼可將其分別傳遞至wfGetCache()ObjectCache::getWANInstance()

以下程式碼片段示範了如何將持續15分鐘的資料庫查詢結果快取至memcached中,然後執行查詢時,系統會優先從memcached取得結果、而不是從資料庫查詢。

class MyExtensionFooBars {
	public function getPopularTen() {
		$cache = ObjectCache::getMainWANInstance();
		
		return $cache->getWithSetCallback(
			// 傳遞給wfMemcKey()的可變參數們就是被用來在memcached之中建立快取的鍵。 
			// 它必須是您正在儲存的查詢所獨有的。
			// 第一個值通常是擴充功能名稱或元件名稱、然後接續的值會告訴您正在儲存的是哪個查詢。
			$cache->makeKey( 'myextension', 'foobars', 'popular', '10' ),
			// 快取 15 分鐘
			$cache::TTL_MINUTE * 15,
			// 快取未命中時用來產生值的函式
			function ( $oldValue, &$ttl, &$setOpts ) {
				$dbr = MediaWikiServices::getInstance()->getConnectionProvider()-> getReplicaDatabase();
				// 根據資料庫複寫延遲去調整存留時間(TTL)
				$setOpts = Database::getCacheSetOptions( $dbr );

				$res = $dbr->select(
					// 您的資料庫查詢指令在此處
					// 請参见Database::select以获取更多文档
				);

				$data = array();
				foreach ( $res as $row ) {
					$data[] = array(
						// 用我們從資料庫剛取得的資料來做點什麼。
						// 例如,若我們要從 page 表格中查找 page_id,可以這樣做:
						'id' => $row->page_id
					);
				}

				return $data;
			}
		);
	}
}

BagOStuff抽象類別與WANObjectCache類別定義並記錄了所有可用函式:

之前的开发笔记

概括來說,我們希望可以將大量資料倒入快取,在需要時隨時調用、且在資料變更時自動清除過期內容。

過期模式

  • 明確的過期時間:memcached讓我們可以在儲存物件時設定其過期時間。 時間到期之後,再次對該物件的請求將發現物件已過期,然後不返回任何結果給我們。
    • 優點:作為最後手段的後備方案,讓那些「可能」被錯誤更新的資料最終從快取中移除
    • 缺點:我們必須事先知道它何時會失效。當我們面對的是用戶的編輯時,這點很難做到!
  • 當我們知道正在執行的操作會導致快取物件失效,卻無法在執行過程中同步更新這些物件時,應主動清除快取物件
    • 優點:相當簡單;該項目將在下次需要時從資料庫重新載入並重新快取
    • 缺點:若此操作會影響大量的相關項目(例如建立或刪除頁面會導致連結/斷鏈的資料表失效,並清除所有連結該頁面的頁面渲染HTML快取),我們可能需要逐一追蹤這些項目並進行大量的更新作業。
  • 在快取的物件上加入時間戳記,並根據依存關係自行設定過期機制
    • 優點:可透過更新單一個所依賴的節點,讓多個物件同時過期
    • 缺點:需要載入更多的內容;多重的依存關係可能更難處理

問答集

問:我能否在Memcached伺服器上以鍵或是正規表達式的某個部份進行搜尋?

A:不行,您只能搜尋精確的鍵。若需進一步了解可執行的操作,請參閱Memcached協定

問:我可以讓多個維基指向同一個 Memcached 伺服器嗎?

A:可以,只要每一個都有不同的維基識別碼($wgDBname )。 在這種情境下,某些特定的快取的鍵會被刻意地共享出來,例如流量限制相關功能的設定。

另见