redis sharding方案
redis sharding方案
Redis集群的目的是實現數據的橫向伸縮,把一塊數據分片保存到多個機器,可以橫向擴展數據庫大小,擴展帶寬,計算能力等。
實現數據分片(集群)方式大致有三種:
(1)客戶端實現數據分片
即客戶端自己計算數據的key應該在哪個機器上存儲和查找,此方法的好處是降低了服務器集群的復雜度,客戶端實現數據分片時,服務器是獨立的,服務器之前沒有任何關聯。多數redis客戶端庫實現了此功能,也叫sharding,這種方式的缺點是客戶端需要實時知道當前集群節點的聯系信息,同時,當添加一個新的節點時,客戶端要支持動態sharding.,多數客戶端實現不支持此功能,需要重啟redis。另一個弊端是redis的HA需要額外考慮。
(2)服務器實現數據分片
其理論是,客戶端隨意與集群中的任何節點通信,服務器端負責計算某個key在哪個機器上,當客戶端訪問某臺機器時,服務器計算對應的key應該存儲在哪個機器,然后把結果返回給客戶端,客戶端再去對應的節點操作key,是一個重定向的過程,此方式是redis3.0正在實現,目前處于beta版本, Redis 3.0的集群同時支持HA功能,某個master節點掛了后,其slave會自動接管。
服務器端實現集群需要客戶端語言實現服務器集群的協議,目前java,php,ruby語言多數有redis-cluster客戶端實現版本。
Redis Cluster原理http://www.cnblogs.com/foxmailed/p/3630875.html
Redis Cluster 是Redis的集群實現,內置數據自動分片機制,集群內部將所有的key映射到16384個Slot中,集群中的每個Redis Instance負責其中的一部分的Slot的讀寫。集群客戶端連接集群中任一Redis Instance即可發送命令,當Redis Instance收到自己不負責的Slot的請求時,會將負責請求Key所在Slot的Redis Instance地址返回給客戶端,客戶端收到后自動將原請求重新發往這個地址,對外部透明。一個Key到底屬于哪個Slot由crc16(key) % 16384 決定。
關于負載均衡,集群的Redis Instance之間可以遷移數據,以Slot為單位,但不是自動的,需要外部命令觸發。
關于集群成員管理,集群的節點(Redis Instance)和節點之間兩兩定期交換集群內節點信息并且更新,從發送節點的角度看,這些信息包括:集群內有哪些節點,IP和PORT是什么,節點名字是什么,節點的狀態(比如OK,PFAIL,FAIL,后面詳述)是什么,包括節點角色(master 或者 slave)等。
關于可用性,集群由N組主從Redis Instance組成。主可以沒有從,但是沒有從 意味著主宕機后主負責的Slot讀寫服務不可用。
一個主可以有多個從,主宕機時,某個從會被提升為主,具體哪個從被提升為主,協議類似于Raft,參見這里。如何檢測主宕機?Redis Cluster采用quorum+心跳的機制。從節點的角度看,節點會定期給其他所有的節點發送Ping,cluster-node-timeout(可配置,秒級)時間內沒有收到對方的回復,則單方面認為對端節點宕機,將該節點標為PFAIL狀態。通過節點之間交換信息收集到quorum個節點都認為這個節點為PFAIL,則將該節點標記為FAIL,并且將其發送給其他所有節點,其他所有節點收到后立即認為該節點宕機。從這里可以看出,主宕機后,至少cluster-node-timeout時間內該主所負責的Slot的讀寫服務不可用。
Redis Cluster Slots是什么?http://www.zhizhihu.com/html/y2014/4590.html
舉個栗子,Redis Cluster下,三個master,三個slave,即每個master有一個slave,那么slots是如何劃分的呢?
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
127.0.0.1:7000
127.0.0.1:7001
127.0.0.1:7002
Adding replica 127.0.0.1:7003 to 127.0.0.1:7000
Adding replica 127.0.0.1:7004 to 127.0.0.1:7001
Adding replica 127.0.0.1:7005 to 127.0.0.1:7002
M: 09a89f7e08b7c00707e3507bea8016e9b4719d78 127.0.0.1:7000
slots:0-5460 (5461 slots) master
M: ddb8a2bc9b93b56a84d8e4c964af24e317767028 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
M: 77335ea34c3d9fcff3a9bf55c1a73490a7153c29 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
S: 67ebdad9de818b13267c1779a941553e88798525 127.0.0.1:7003
replicates 09a89f7e08b7c00707e3507bea8016e9b4719d78
S: a3f6c70725c25f92c35816966aee9ee7248e4a33 127.0.0.1:7004
replicates ddb8a2bc9b93b56a84d8e4c964af24e317767028
S: 2a58a4ca50e0ad733e83be3eb4cbbc8d9103fbbe 127.0.0.1:7005
注意這里,M: 09a89f7e08b7c00707e3507bea8016e9b4719d78 127.0.0.1:7000
slots:0-5460 (5461 slots) master
M: ddb8a2bc9b93b56a84d8e4c964af24e317767028 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
M: 77335ea34c3d9fcff3a9bf55c1a73490a7153c29 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
好了,可以看到slots就是這樣分配的。
如果一個key經過crc16后,如果他的slot為16381,那么他就在id為77335ea34c3d9fcff3a9bf55c1a73490a7153c29 的master上。
(3)通過代理服務器實現數據分片
此方式是借助一個代理服務器實現數據分片,客戶端直接與proxy聯系,proxy計算集群節點信息,并把請求發送到對應的集群節點。降低了客戶端的復雜度,需要proxy收集集群節點信息。Twemproxy是推ter開源的,實現這一功能的proxy。這個實現方式在客戶端和服務器之間加了一個proxy,但這是在redis 3.0穩定版本出來之前官方推薦的方式。結合redis-sentinel的HA方案,是個不錯的組合。
參考:http://www.zhizhihu.com/html/y2014/4590.html