分片(partitioning)就是將你的數(shù)據(jù)拆分到多個 Redis 實例的過程,這樣每個實例將只包含所有鍵的子集。本文第一部分將向你介紹分片的概念,第二部分將向你展示 Redis 分片的可選方案。
Redis 的分片承擔(dān)著兩個主要目標(biāo):
有很多不同的分片標(biāo)準(zhǔn)(criteria)。假想我們有 4 個 Redis 實例 R0,R1,R2,R3,還有很多表示用戶的鍵,像 user:1,user:2,… 等等,我們能找到不同的方式來選擇一個指定的鍵存儲在哪個實例中。換句話說,有許多不同的辦法來映射一個鍵到一個指定的 Redis 服務(wù)器。
最簡單的執(zhí)行分片的方式之一是范圍分片(range partitioning),通過映射對象的范圍到指定的 Redis 實例來完成分片。例如,我可以假設(shè)用戶從 ID 0 到 ID 10000 進入實例 R0,用戶從 ID 10001 到 ID 20000 進入實例 R1,等等。
這套辦法行得通,并且事實上在實踐中被采用,然而,這有一個缺點,就是需要一個映射范圍到實例的表格。這張表需要管理,不同類型的對象都需要一個表,所以范圍分片在 Redis 中常常并不可取,因為這要比替他分片可選方案低效得多。
一種范圍分片的替代方案是哈希分片(hash partitioning)。這種模式適用于任何鍵,不需要鍵像 object_name:
有許多其他的方式可以分片,從這兩個例子中你就可以知道了。一種哈希分片的高級形式稱為一致性哈希(consistent hashing),被一些 Redis 客戶端和代理實現(xiàn)。
分片可由軟件棧中的不同部分來承擔(dān)。
Redis 的一些特性與分片在一起時玩轉(zhuǎn)的不是很好:
盡管無論是將 Redis 作為數(shù)據(jù)存儲還是緩存,Redis 的分片概念上都是一樣的,但是作為數(shù)據(jù)存儲時有一個重要的局限。當(dāng) Redis 作為數(shù)據(jù)存儲時,一個給定的鍵總是映射到相同的 Redis 實例。當(dāng) Redis 作為緩存時,如果一個節(jié)點不可用而使用另一個節(jié)點,這并不是一個什么大問題,按照我們的愿望來改變鍵和實例的映射來改進系統(tǒng)的可用性(就是系統(tǒng)回復(fù)我們查詢的能力)。
一致性哈希實現(xiàn)常常能夠在指定鍵的首選節(jié)點不可用時切換到其他節(jié)點。類似的,如果你添加一個新節(jié)點,部分?jǐn)?shù)據(jù)就會開始被存儲到這個新節(jié)點上。
這里的主要概念如下:
我們已經(jīng)知道分片存在的一個問題,除非我們使用 Redis 作為緩存,增加和刪除節(jié)點是一件很棘手的事情,使用固定的鍵和實例映射要簡單得多。
然而,數(shù)據(jù)存儲的需求可能一直在變化。今天我可以接受 10 個 Redis 節(jié)點(實例),但是明天我可能就需要 50 個節(jié)點。
因為 Redis 只有相當(dāng)少的內(nèi)存占用(footprint)而且輕量級(一個空閑的實例只是用 1MB 內(nèi)存),一個簡單的解決辦法是一開始就開啟很多的實例。即使你一開始只有一臺服務(wù)器,你也可以在第一天就決定生活在分布式的世界里,使用分片來運行多個 Redis 實例在一臺服務(wù)器上。
你一開始就可以選擇很多數(shù)量的實例。例如,32 或者 64 個實例能滿足大多數(shù)的用戶,并且為未來的增長提供足夠的空間。
這樣,當(dāng)你的數(shù)據(jù)存儲需要增長,你需要更多的 Redis 服務(wù)器,你要做的就是簡單地將實例從一臺服務(wù)器移動到另外一臺。當(dāng)你新添加了第一臺服務(wù)器,你就需要把一半的 Redis 實例從第一臺服務(wù)器搬到第二臺,如此等等。
使用 Redis 復(fù)制,你就可以在很小或者根本不需要停機時間內(nèi)完成移動數(shù)據(jù):
到目前為止,我們從理論上討論了 Redis 分片,但是實踐情況如何呢?你應(yīng)該使用什么系統(tǒng)呢?
Redis 集群是自動分片和高可用的首選方式。當(dāng)前還不能完全用于生產(chǎn)環(huán)境,但是已經(jīng)進入了 beta 階段,所以我們推薦你開始小試牛刀。你可以從集群教程(請持續(xù)關(guān)注本公眾賬號后續(xù)文章,譯者注)中獲取更多 Redis 集群的相關(guān)信息。
一旦 Redis 集群可用,以及支持 Redis 集群的客戶端可用,Redis 集群將會成為 Redis 分片的事實標(biāo)準(zhǔn)。
Redis 集群是查詢路由和客戶端分片的混合模式。
Twemproxy 是 Twitter 開發(fā)的一個支持 Memcached ASCII 和 Redis 協(xié)議的代理。它是單線程的,由 C 語言編寫,運行非常的快。他是基于 Apache 2.0 許可的開源項目。
Twemproxy 支持自動在多個 Redis 實例間分片,如果節(jié)點不可用時,還有可選的節(jié)點排除支持(這會改變鍵和實例的映射,所以你應(yīng)該只在將 Redis 作為緩存是才使用這個特性)。
這并不是單點故障(single point of failure),因為你可以啟動多個代理,并且讓你的客戶端連接到第一個接受連接的代理。
從根本上說,Twemproxy 是介于客戶端和 Redis 實例之間的中間層,這就可以在最下的額外復(fù)雜性下可靠地處理我們的分片。這是當(dāng)前我們建議的處理 Redis 分片的方式。你可以閱讀更多關(guān)于 Twemproxy 的信息(作者的這篇博客文章 http://antirez.com/news/44,譯者注)。
Twemproxy 之外的可選方案,是使用實現(xiàn)了客戶端分片的客戶端,通過一致性哈?;蛘邉e的類似算法。有多個支持一致性哈希的 Redis 客戶端,例如 Redis-rb 和 Predis。
請查看完整的 Redis 客戶端列表,看看是不是有支持你的編程語言的,并實現(xiàn)了一致性哈希的成熟客戶端。