分區(qū)在我的理解就是原本一個(gè)Redis處理所有的get/set請(qǐng)求铡俐,現(xiàn)在用多個(gè)Redis實(shí)例來分擔(dān)get/set 請(qǐng)求捞高。
- 為什么要使用分區(qū)谣辞?
- 擴(kuò)容
- 提升計(jì)算能力宋距,提高帶寬
分區(qū)標(biāo)準(zhǔn)
- 范圍分區(qū)
就是將不同范圍的對(duì)象映射到不同Redis實(shí)例变过。比如說埃元,用戶ID從0到10000的都被存儲(chǔ)到R0,用戶ID從10001到20000被存儲(chǔ)到R1,依此類推。
這是一種可行方案并且很多人已經(jīng)在使用媚狰。但是這種方案也有缺點(diǎn)岛杀,你需要建一張表存儲(chǔ)數(shù)據(jù)到redis實(shí)例的映射關(guān)系。這張表需要非常謹(jǐn)慎地維護(hù)并且需要為每一類對(duì)象建立映射關(guān)系崭孤,所以redis范圍分區(qū)通常并不像你想象的那樣運(yùn)行类嗤,比另外一種分區(qū)方案效率要低很多。 - Hash分區(qū)
1. 使用散列函數(shù) (如 crc32 )將鍵名稱轉(zhuǎn)換為一個(gè)數(shù)字辨宠。例:鍵foobar, 使用crc32(foobar)函數(shù)將產(chǎn)生散列值93024922遗锣。
2. 對(duì)轉(zhuǎn)換后的散列值進(jìn)行取模,以產(chǎn)生一個(gè)0到3的數(shù)字嗤形,以便可以使這個(gè)key映射到4個(gè)Redis實(shí)例當(dāng)中的一個(gè)精偿。93024922 % 4 等于 2, 所以 foobar 會(huì)被存儲(chǔ)到第2個(gè)Redis實(shí)例。 R2 注意: 對(duì)一個(gè)數(shù)字進(jìn)行取模,在大多數(shù)編程語言中是使用運(yùn)算符%
分區(qū)的實(shí)現(xiàn)方案
- 客戶端分區(qū)
就是由客戶端自己決定要將Key存放在哪個(gè)實(shí)例笔咽,再去哪個(gè)實(shí)例獲取 - 代理分區(qū)
客戶端依賴一個(gè)代理搔预,代理決定去哪個(gè)節(jié)點(diǎn)寫數(shù)據(jù)或者讀數(shù)據(jù)。代理根據(jù)分區(qū)規(guī)則決定請(qǐng)求哪些Redis實(shí)例叶组,然后根據(jù)Redis的響應(yīng)結(jié)果返回給客戶端拯田。redis和memcached的一種代理實(shí)現(xiàn)就是Twemproxy - 查詢路由
客戶端隨機(jī)地請(qǐng)求任意一個(gè)redis實(shí)例,然后由Redis將請(qǐng)求轉(zhuǎn)發(fā)給正確的Redis節(jié)點(diǎn)
分區(qū)的缺點(diǎn)
- 涉及多個(gè)key的操作通常不會(huì)被支持甩十。例如你不能對(duì)兩個(gè)集合求交集船庇,多個(gè)Key的事務(wù)
- 備份/恢復(fù) 復(fù)雜化
- 分區(qū)使用的粒度是key,zset 功能受到限制
- 擴(kuò)容和縮容操作復(fù)雜
用作緩存和持久化分區(qū)的不同
使用途徑不一樣Redis分區(qū)的實(shí)現(xiàn)還是有點(diǎn)不一樣的侣监。當(dāng)把Redis當(dāng)做一個(gè)持久化存儲(chǔ)時(shí)鸭轮,一個(gè)key必須嚴(yán)格地每次被映射到同一個(gè)Redis實(shí)例。當(dāng)把Redis當(dāng)做一個(gè)緩存時(shí)达吞,即使Redis的其中一個(gè)節(jié)點(diǎn)不可用,就算數(shù)據(jù)發(fā)生了丟失张弛,我們還可以去Mysql等數(shù)據(jù)庫(kù)拉取數(shù)據(jù),淡然我們可用任意的規(guī)則更改映射酪劫,提高系統(tǒng)的高可用性吞鸭,比如使用一致性Hash算法,這種方法能夠?qū)崿F(xiàn)當(dāng)一個(gè)key的首選的節(jié)點(diǎn)不可用時(shí)切換至其他節(jié)點(diǎn)覆糟。同樣地刻剥,如果你增加了一個(gè)新節(jié)點(diǎn),立刻就會(huì)有新的key被分配至這個(gè)新節(jié)點(diǎn)滩字。
- 重要結(jié)論如下:
- 如果Redis被當(dāng)做緩存使用造虏,使用一致性哈希實(shí)現(xiàn)動(dòng)態(tài)擴(kuò)容縮容。
- 如果Redis被當(dāng)做一個(gè)持久化存儲(chǔ)使用麦箍,必須使用固定的keys-to-nodes映射關(guān)系漓藕,節(jié)點(diǎn)的數(shù)量一旦確定不能變化。否則的話(即Redis節(jié)點(diǎn)需要?jiǎng)討B(tài)變化的情況)挟裂,必須使用可以在運(yùn)行時(shí)進(jìn)行數(shù)據(jù)再平衡的一套系統(tǒng)享钞,而當(dāng)前只有Redis集群可以做到這樣 - Redis 集群已經(jīng)可用 2015.4.1.
預(yù)分片
如果我們要將Redis作為持久化,一般情況下隨著時(shí)間的推移诀蓉,數(shù)據(jù)存儲(chǔ)需求總會(huì)發(fā)生變化栗竖。今天可能10個(gè)Redis節(jié)點(diǎn)就夠了,但是明天可能就需要增加到50個(gè)節(jié)點(diǎn)渠啤,這是十分麻煩的狐肢。為防止以后的擴(kuò)容,最好的辦法就是一開始就啟動(dòng)較多實(shí)例沥曹。即便你只有一臺(tái)服務(wù)器份名,你也可以一開始就讓Redis以分布式的方式運(yùn)行碟联,使用分區(qū),在同一臺(tái)服務(wù)器上啟動(dòng)多個(gè)實(shí)例(偽集群)同窘。
一開始就多設(shè)置幾個(gè)Redis實(shí)例玄帕,例如32或者64個(gè)實(shí)例部脚,對(duì)大多數(shù)用戶來說這操作起來可能比較麻煩想邦,但是從長(zhǎng)久來看做這點(diǎn)犧牲是值得的。
這樣的話委刘,當(dāng)你的數(shù)據(jù)不斷增長(zhǎng)丧没,需要更多的Redis服務(wù)器時(shí),你需要做的就是僅僅將Redis實(shí)例從一臺(tái)服務(wù)遷移到另外一臺(tái)服務(wù)器而已(而不用考慮重新分區(qū)的問題)锡移。一旦你添加了另一臺(tái)服務(wù)器呕童,你需要將你一半的Redis實(shí)例從第一臺(tái)機(jī)器遷移到第二臺(tái)機(jī)器。
大概的操作步驟是這樣:
- 啟動(dòng)一個(gè)空的實(shí)例
new
在另外一臺(tái)機(jī)子上淆珊; - 把
new
配置為你的的源實(shí)例(要擴(kuò)容的實(shí)例)的從節(jié)點(diǎn)夺饲; - 關(guān)閉客戶端
- 更改客戶端的配置(連接到新機(jī)子的Ip)
- 將
new
設(shè)置為主節(jié)點(diǎn)SLAVEOF NO ONE
- 重啟客戶端
- 關(guān)閉源實(shí)例
分區(qū)的可選方案
- 首選Redis Cluster
- 使用推特開源的代理
twemproxy
- 使用支持一致性哈希的客戶端