作者:Grey
原文地址:Redis學習筆記八:集群模式
前面提到的Redis學習筆記七:主從復制和哨兵只能解決Redis的單點壓力大和單點故障問題,接下來要講的Redis Cluster模式,主要是用來解決Redis的單點容量問題。
如何來解決Redis單點容量問題呢?
如果數據可以拆分,我們可以讓不同業務的客戶端打到不同的Redis實例中。
如果數據不能拆分,我們有如下方式:
方案2-1 modula方式
可以通過Hash加上取模的方式來定位打到哪個Redis實例中。
這種方式的弊端在於:模數值固定,會影響分布式下的擴展性。
方案2-2 random方式
即每次請求redis的實例是隨機的,一部分客戶端負責push數據,一部分客戶端負責消費數據,這樣的場景可以適用於消息隊列。
方案2-3 ketama方式
這種方式是通過一致性Hash算法(沒有取模),規划成一個環形,環形上有很多虛擬節點,每次選擇的實例通過hash算法對應到具體的一個節點。模型如下:
Client1~Client4通過Hash分別找到了環上A~B四個點

這種方式的優點在於:增加節點的時候可以分擔其他節點的壓力,不會造成全局洗牌。
缺點在於:新增節點造成一小部分數據不能命中,會使得緩存擊穿,壓到mysql
解決方案:取離我最近的2個物理節點
modula,random和ketama方式都是從客戶端入手,因為每個客戶端都需要與redis實例建立連接,所以,這種情況會導致連接的成本很高。如何解決這個問題呢?
我們可以在客戶端和Redis之間增加一個代理層,通過代理層去實現原先在客戶端要實現的三個方案。

此時,代理層就容易成為一個單點故障。所以代理可以做集群,然后最前端通過LVS來做負載均衡,防止LVS掛掉,可以通過KeepAlived來調配LVS,同時,KeepAlived也可以作為代理層健康檢查的工具。整個架構圖如下:

這三種模式的弊端都在於:只能讓Redis做緩存,無法做數據庫。(因為數據會丟失)
要解決這個問題,可以通過預分區的方式,增加槽位的概念:http://www.redis.cn/topics/cluster-tutorial.html
可以通過redis-cluster 模式(無主模型)來解決。

客戶端隨機地請求任意一個redis實例,然后由Redis將請求轉發給正確的Redis節點。Redis Cluster實現了一種混合形式的查詢路由,但並不是直接將請求從一個redis節點轉發到另一個redis節點,而是在客戶端的幫助下直接redirected到正確的redis節點。
但是數據分治的時候,會帶來一個問題,無法做聚合操作,怎么解決呢?
我們可以使用hash tag,讓同一組key打到同一個redis實例上面,並且對同一hash tag下的key可以進行聚合操作。
Twemproxy實戰
Twemproxy 也叫 nutcraker。是 Twitter 開源的一個 Redis 和 Memcache 代理服務器,主要用於管理 Redis 和 Memcached 集群,減少與Cache 服務器直接連接的數量。
啟動3個redis服務實例:假設為:
- 6379
- 6381
- 6380

在/usr/local/src目錄下,下載最新的twemproxy的源碼包
cd /usr/local/src
## 下載源碼
wget https://github.com/twitter/twemproxy/archive/refs/tags/v0.4.1.tar.gz
## 解壓
tar xf v0.4.1.tar.gz
## 重命名
mv twemproxy-0.4.1/ twemproxy/
接下來按照官方步驟編譯安裝
yum install automake libtool -y
cd /usr/local/src/twemproxy/
autoreconf -fvi
./configure --enable-debug=full
make
src/nutcracker -h
## 安裝成服務
cp nutcracker.init /etc/init.d/nutcracker
chmod +x /etc/init.d/nutcracker
mkdir /etc/nutcracker
cp /usr/local/src/twemproxy/conf/* /etc/nutcracker/
cp /usr/local/src/twemproxy/src/nutcracker /usr/bin
接下來修改twemproxy的配置文件
vi /etc/nutcracker/nutcracker.yml
修改為:
alpha:
listen: 127.0.0.1:22121
hash: fnv1a_64
distribution: ketama
auto_eject_hosts: true
redis: true
server_retry_timeout: 2000
server_failure_limit: 1
servers:
- 127.0.0.1:6379:1
- 127.0.0.1:6380:1
- 127.0.0.1:6381:1
啟動
service nutcracker start
連接到代理:
redis-cli -p 22121
127.0.0.1:22121> set k1 1
OK
127.0.0.1:22121> get k1
"1"
不支持的一些操作。
127.0.0.1:22121> keys *
Error: Server closed the connection
127.0.0.1:22121> watch k1
Error: Server closed the connection
127.0.0.1:22121> mult
Error: Server closed the connection
127.0.0.1:22121> multi
Error: Server closed the connection
predix實戰
Predixy 是一款高性能全特征redis代理,支持redis-sentinel和redis-cluster。
我們配置一套哨兵來監控兩套主從復制集群,並用predix作為代理。
環境准備
第一套主從:
主:6380
從:6379
第二套主從:
主:16380
從:16379
啟動這兩套實例
哨兵26379
配置為:
port 26379
sentinel monitor mymaster1 127.0.0.1 6380 2
sentinel monitor mymaster2 127.0.0.1 16380 2
哨兵26380
配置為
port 26380
sentinel monitor mymaster1 127.0.0.1 6380 2
sentinel monitor mymaster2 127.0.0.1 16380 2
啟動哨兵
[root@redis01 sentinel]# ps -ef|grep redis
root 1456 1443 0 20:34 pts/1 00:00:00 redis-server 127.0.0.1:6380
root 1474 1463 0 20:35 pts/2 00:00:00 redis-server 127.0.0.1:6379
root 1505 1488 0 20:39 pts/3 00:00:00 redis-server 127.0.0.1:16380
root 1525 1512 0 20:39 pts/4 00:00:00 redis-server 127.0.0.1:16379
root 1574 1559 0 20:44 pts/5 00:00:00 redis-server *:26380 [sentinel]
root 1592 1581 0 20:44 pts/6 00:00:00 redis-server *:26379 [sentinel]
配置predixy
cd /usr/local
## 下載predixy的二進制安裝包
wget https://github.com/joyieldInc/predixy/releases/download/1.0.5/predixy-1.0.5-bin-amd64-linux.tar.gz
## 解壓
tar xf predixy-1.0.5-bin-amd64-linux.tar.gz
## 重命名
mv predixy-1.0.5 predixy
cp /usr/local/predixy/bin/predixy /usr/bin/
修改配置
vi /usr/local/predixy/conf/predixy.conf
打開如下兩個配置
Bind 0.0.0.0:7617
## 默認try.conf,注釋掉,打開sentinel.conf
# Include cluster.conf
Include sentinel.conf
#Include try.conf
修改sentinel.conf配置文件
vi /usr/local/predixy/conf/sentinel.conf
增加如下配置項
SentinelServerPool {
Databases 16
Hash crc16
HashTag "{}"
Distribution modula
MasterReadPriority 60
StaticSlaveReadPriority 50
DynamicSlaveReadPriority 50
RefreshInterval 1
ServerTimeout 1
ServerFailureLimit 10
ServerRetryTimeout 1
KeepAlive 120
Sentinels {
+ 127.0.0.1:26379
+ 127.0.0.1:26380
}
Group mymaster1 {
}
Group mymaster2 {
}
}
啟動
predixy /usr/local/predixy/conf/predixy.conf
測試
[root@redis01 conf]# redis-cli -p 7617
127.0.0.1:7617> set k1 aaa
OK
127.0.0.1:7617> get k1
"aaa"
注:predixy的事務只支持單group
redis-cluster實驗
redis自帶的模式,我們可以通過如下方式來搭建一個redis-cluster
# 進入redis源碼目錄
cd /usr/local/src/redis/utils/create-cluster
執行start
```sh
[root@redis01 create-cluster]# ./create-cluster start
Starting 30001
Starting 30002
Starting 30003
Starting 30004
Starting 30005
Starting 30006
執行create
./create-cluster create
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 127.0.0.1:30005 to 127.0.0.1:30001
Adding replica 127.0.0.1:30006 to 127.0.0.1:30002
Adding replica 127.0.0.1:30004 to 127.0.0.1:30003
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 7be080333e7acc60e207374f27d6f86f15d3c466 127.0.0.1:30001
slots:[0-5460] (5461 slots) master
M: 8e3d9ca761726e57af2c4ca5c092599e6977a8a8 127.0.0.1:30002
slots:[5461-10922] (5462 slots) master
M: 71755fb0c3fcb771432467155585b40efafae80b 127.0.0.1:30003
slots:[10923-16383] (5461 slots) master
S: 8eb1de8a35bdfced30ef70d6faedae5cf76b8dda 127.0.0.1:30004
replicates 7be080333e7acc60e207374f27d6f86f15d3c466
S: f4d69a577b0992191517e1fbb71ee7598a0b8527 127.0.0.1:30005
replicates 8e3d9ca761726e57af2c4ca5c092599e6977a8a8
S: 4138b3e66c71ededf9362327bb5b2562da688155 127.0.0.1:30006
replicates 71755fb0c3fcb771432467155585b40efafae80b
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
..
>>> Performing Cluster Check (using node 127.0.0.1:30001)
M: 7be080333e7acc60e207374f27d6f86f15d3c466 127.0.0.1:30001
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 4138b3e66c71ededf9362327bb5b2562da688155 127.0.0.1:30006
slots: (0 slots) slave
replicates 71755fb0c3fcb771432467155585b40efafae80b
M: 71755fb0c3fcb771432467155585b40efafae80b 127.0.0.1:30003
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
M: 8e3d9ca761726e57af2c4ca5c092599e6977a8a8 127.0.0.1:30002
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: f4d69a577b0992191517e1fbb71ee7598a0b8527 127.0.0.1:30005
slots: (0 slots) slave
replicates 8e3d9ca761726e57af2c4ca5c092599e6977a8a8
S: 8eb1de8a35bdfced30ef70d6faedae5cf76b8dda 127.0.0.1:30004
slots: (0 slots) slave
replicates 7be080333e7acc60e207374f27d6f86f15d3c466
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
客戶端連接30001~30004任意一個服務都可以。
Redis 用作分布式鎖
- setnx
- 過期時間
- 多線程(守護線程)用於延長過期時間
redisson
