【轉載請注明出處】: https://www.jianshu.com/p/41f97c494fc4
Redis 叢集解決方案有哪些
Redis 的叢集解決方案有社群的,也有官方的,社群的解決方案有 Codis 和Twemproxy,Codis是由我國的豌豆莢團隊開源的,Twemproxy是Twitter團隊的開源的;官方的叢集解決方案就是 Redis Cluster,這是由 Redis 官方團隊來實作的。下面的清單可以很明顯地表達出三者的不同點。
Codis | Twemproxy | Redis Cluster | |
---|---|---|---|
resharding without restarting cluster | Yes | No | |
pipeline | |||
hash tags for multi-key operations | |||
multi-key operations while resharding | - | No( details ) | |
Redis clients supporting | Any clients | Clients have to support cluster protocol |
codis和twemproxy最大的差別有兩個:
- codis支援動态水準擴充,對client完全透明不影響服務的情況下可以完成增減redis執行個體的操作;
- codis是用go語言寫的并支援多線程,twemproxy用C并隻用單線程。 後者又意味着:codis在多核機器上的性能會好于twemproxy;codis的最壞響應時間可能會因為GC的STW而變大,不過go1.5釋出後會顯著降低STW的時間;如果隻用一個CPU的話go語言的性能不如C,是以在一些短連接配接而非長連接配接的場景中,整個系統的瓶頸可能變成accept新tcp連接配接的速度,這時codis的性能可能會差于twemproxy。
codis和redis cluster的差別:
- redis cluster基于smart client和無中心的設計,client必須按key的哈希将請求直接發送到對應的節點。這意味着:使用官方cluster必須要等對應語言的redis driver對cluster支援的開發和不斷成熟;client不能直接像單機一樣使用pipeline來提高效率,想同時執行多個請求來提速必須在client端自行實作異步邏輯。 而codis因其有中心節點、基于proxy的設計,對client來說可以像對單機redis一樣去操作proxy(除了一些指令不支援),還可以繼續使用pipeline并且如果背景redis有多個的話速度會顯著快于單redis的pipeline。
- codis使用zookeeper來作為輔助,這意味着單純對于redis叢集來說需要額外的機器搭zk。
Codis介紹
Codis 是一個分布式 Redis 解決方案, 對于上層的應用來說, 連接配接到 Codis Proxy 和連接配接原生的 Redis Server 沒有顯著差別 (
不支援的指令清單), 上層應用可以像使用單機的 Redis 一樣使用, Codis 底層會處理請求的轉發, 不停機的資料遷移等工作, 所有後邊的一切事情, 對于前面的用戶端來說是透明的, 可以簡單的認為後邊連接配接的是一個記憶體無限大的 Redis 服務。
Codis 3.x 由以下元件組成:
- Codis Server:基于 redis-3.2.8 分支開發。增加了額外的資料結構,以支援 slot 有關的操作以及資料遷移指令。具體的修改可以參考文檔 redis 的修改 。
- Codis Proxy:用戶端連接配接的 Redis 代理服務, 實作了 Redis 協定。 除部分指令不支援以外( ),表現的和原生的 Redis 沒有差別(就像 Twemproxy)。
- 對于同一個業務叢集而言,可以同時部署多個 codis-proxy 執行個體;
- 不同 codis-proxy 之間由 codis-dashboard 保證狀态同步。
- Codis Dashboard:叢集管理工具,支援 codis-proxy、codis-server 的添加、删除,以及據遷移等操作。在叢集狀态發生改變時,codis-dashboard 維護叢集下所有 codis-proxy 的狀态的一緻性。
- 對于同一個業務叢集而言,同一個時刻 codis-dashboard 隻能有 0個或者1個;
- 所有對叢集的修改都必須通過 codis-dashboard 完成。
- Codis Admin:叢集管理的指令行工具。
- 可用于控制 codis-proxy、codis-dashboard 狀态以及通路外部存儲。
- Codis FE:叢集管理界面。
- 多個叢集執行個體共享可以共享同一個前端展示頁面;
- 通過配置檔案管理後端 codis-dashboard 清單,配置檔案可自動更新。
- Storage:為叢集狀态提供外部存儲。
- 提供 Namespace 概念,不同叢集的會按照不同 product name 進行組織;
- 目前僅提供了 Zookeeper、Etcd、Fs 三種實作,但是提供了抽象的 interface 可自行擴充。
Codis 分片原理
在Codis中,Codis會把所有的key分成1024個槽,這1024個槽對應着的就是Redis的叢集,這個在Codis中是會在記憶體中維護着這1024個槽與Redis執行個體的映射關系。這個槽是可以配置,可以設定成 2048 或者是4096個。看你的Redis的節點數量有多少,偏多的話,可以設定槽多一些。
Codis中key的配置設定算法,先是把key進行CRC32 後,得到一個32位的數字,然後再hash%1024後得到一個餘數,這個值就是這個key對應着的槽,這槽後面對應着的就是redis的執行個體。
CRC32:CRC本身是“備援校驗碼”的意思,CRC32則表示會産生一個32bit(8位十六進制數)的校驗值。由于CRC32産生校驗值時源資料塊的每一個bit(位)都參與了計算,是以資料塊中即使隻有一位發生了變化,也會得到不同的CRC32值。
Codis之間的槽位同步
Codis把槽位資訊同步的工作交給了ZooKeeper來管理,當Codis的Codis Dashbord 改變槽位的資訊的時候,其他的Codis節點會監聽到ZooKeeper的槽位變化,會及時同步過來。如圖:
Codis中的擴容
因為Codis是一個代理中間件,是以這個當需要擴容Redis執行個體的時候,可以直接增加redis節點。在槽位配置設定的時候,可以手動指定Codis Dashbord來為新增的節點來配置設定特定的槽位。
在Codis中實作了自定義的掃描指令SLOTSSCAN,可以掃描指定的slot下的所有的key,将這些key遷移到新的Redis的節點中(話外語:這個是Codis定制化的其中一個好處)。
首先,在遷移的時候,會在原來的Redis節點和新的Redis裡都儲存着遷移的槽位資訊,在遷移的過程中,如果有key打進将要遷移或者正在遷移的舊槽位的時候,這個時候Codis的處理機制是,先是将這個key強制遷移到新的Redis節點中,然後再告訴Codis,下次如果有新的key的打在這個槽位中的話,那麼轉發到新的節點。
自動均衡政策
面對着上面講的遷移政策,如果有成千上萬個節點新增進來,都需要我們手動去遷移嗎?那豈不是得累死啊。當然,Codis也是考慮到了這一點,是以提供了自動均衡政策。自動均衡政策是這樣的,Codis 會在機器空閑的時候,觀察Redis中的執行個體對應着的slot數,如果不平衡的話就會自動進行遷移。
Codis安裝
依賴環境準備
下面這兩個依賴環境的搭建這裡不再介紹。
- 安裝Zookeeper
- 安裝Go
1. 下載下傳Codis安裝包
在
官方的釋出頁找到最新的釋出版本下載下傳最新版3.2.2,如需要編譯安裝請參考
官方的編譯安裝說明下載下傳安裝包之後解壓并重命名目錄,進入解壓目錄建立
config
檔案夾用來放置配置檔案位址,建立
logs
檔案夾将來放日志檔案。
2.安裝codis-dashboard(叢集管理工具)
config
檔案夾中建立配置檔案
dashboard.toml
(這些
配置檔案模闆在源碼
config
目錄中可以找到),檔案内容:
##################################################
# #
# Codis-Dashboard #
# #
##################################################
# Set Coordinator, only accept "zookeeper" & "etcd" & "filesystem".
# for zookeeper/etcd, coorinator_auth accept "user:password"
# Quick Start
#coordinator_name = "filesystem"
#coordinator_addr = "/tmp/codis"
coordinator_name = "zookeeper"
coordinator_addr = "zk1:2181,zk2:2182,zk3:2183"
coordinator_auth = ""
# Set Codis Product Name/Auth.
product_name = "codis-demo"
product_auth = ""
# Set bind address for admin(rpc), tcp only.
admin_addr = "0.0.0.0:18080"
# Set arguments for data migration (only accept 'sync' & 'semi-async').
migration_method = "semi-async"
migration_parallel_slots = 100
migration_async_maxbulks = 200
migration_async_maxbytes = "32mb"
migration_async_numkeys = 500
migration_timeout = "30s"
# Set configs for redis sentinel.
sentinel_client_timeout = "10s"
sentinel_quorum = 2
sentinel_parallel_syncs = 1
sentinel_down_after = "30s"
sentinel_failover_timeout = "5m"
sentinel_notification_script = ""
sentinel_client_reconfig_script = ""
為了友善管理建立啟動腳本
start-dashboard.sh
,腳本内容:
#!/bin/sh
#set -x
nohup ./codis-dashboard --ncpu=4 --config=./config/dashboard.toml --log=./logs/dashboard.log --log-level=WARN &>/dev/null &
執行啟動腳本啟動dashboard,然後浏覽器通路18080端口已經可以傳回目前叢集資訊。
啟動參數說明:
$ ./codis-dashboard -h
Usage:
codis-dashboard [--ncpu=N] [--config=CONF] [--log=FILE] [--log-level=LEVEL] [--host-admin=ADDR]
codis-dashboard --default-config
codis-dashboard --version
Options:
--ncpu=N 最大使用 CPU 個數
-c CONF, --config=CONF 指定啟動配置檔案
-l FILE, --log=FILE 設定 log 輸出檔案
--log-level=LEVEL 設定 log 輸出等級:INFO,WARN,DEBUG,ERROR;預設INFO,推薦WARN
預設配置檔案:
$ ./codis-dashboard --default-config | tee dashboard.toml
##################################################
# #
# Codis-Dashboard #
# #
##################################################
# Set Coordinator, only accept "zookeeper" & "etcd"
coordinator_name = "zookeeper"
coordinator_addr = "127.0.0.1:2181"
# Set Codis Product {Name/Auth}.
product_name = "codis-demo"
product_auth = ""
# Set bind address for admin(rpc), tcp only.
admin_addr = "0.0.0.0:18080"
| 參數 | 說明 |
| - | - |
| coordinator_name | 外部存儲類型,接受 zookeeper/etcd |
| coordinator_addr | 外部存儲位址 |
| product_name | 叢集名稱,滿足正則 w[w.-]* |
| product_auth | 叢集密碼,預設為空 |
| admin_addr | RESTful API 端口 |
3.安裝codis-proxy(用戶端連接配接的 Redis 代理服務)
config
proxy.toml
,檔案内容:
##################################################
# #
# Codis-Proxy #
# #
##################################################
# Set Codis Product Name/Auth.
product_name = "codis-demo"
product_auth = ""
# Set auth for client session
# 1. product_auth is used for auth validation among codis-dashboard,
# codis-proxy and codis-server.
# 2. session_auth is different from product_auth, it requires clients
# to issue AUTH <PASSWORD> before processing any other commands.
session_auth = ""
# Set bind address for admin(rpc), tcp only.
admin_addr = "0.0.0.0:11080"
# Set bind address for proxy, proto_type can be "tcp", "tcp4", "tcp6", "unix" or "unixpacket".
proto_type = "tcp4"
proxy_addr = "0.0.0.0:19000"
# Set jodis address & session timeout
# 1. jodis_name is short for jodis_coordinator_name, only accept "zookeeper" & "etcd".
# 2. jodis_addr is short for jodis_coordinator_addr
# 3. jodis_auth is short for jodis_coordinator_auth, for zookeeper/etcd, "user:password" is accepted.
# 4. proxy will be registered as node:
# if jodis_compatible = true (not suggested):
# /zk/codis/db_{PRODUCT_NAME}/proxy-{HASHID} (compatible with Codis2.0)
# or else
# /jodis/{PRODUCT_NAME}/proxy-{HASHID}
jodis_name = "zookeeper"
jodis_addr = "zk1:2181,zk2:2182,zk3:2183"
jodis_auth = ""
jodis_timeout = "20s"
jodis_compatible = false
# Set datacenter of proxy.
proxy_datacenter = ""
# Set max number of alive sessions.
proxy_max_clients = 1000
# Set max offheap memory size. (0 to disable)
proxy_max_offheap_size = "1024mb"
# Set heap placeholder to reduce GC frequency.
proxy_heap_placeholder = "256mb"
# Proxy will ping backend redis (and clear 'MASTERDOWN' state) in a predefined interval. (0 to disable)
backend_ping_period = "5s"
# Set backend recv buffer size & timeout.
backend_recv_bufsize = "128kb"
backend_recv_timeout = "30s"
# Set backend send buffer & timeout.
backend_send_bufsize = "128kb"
backend_send_timeout = "30s"
# Set backend pipeline buffer size.
backend_max_pipeline = 20480
# Set backend never read replica groups, default is false
backend_primary_only = false
# Set backend parallel connections per server
backend_primary_parallel = 1
backend_replica_parallel = 1
# Set backend tcp keepalive period. (0 to disable)
backend_keepalive_period = "75s"
# Set number of databases of backend.
backend_number_databases = 16
# If there is no request from client for a long time, the connection will be closed. (0 to disable)
# Set session recv buffer size & timeout.
session_recv_bufsize = "128kb"
session_recv_timeout = "30m"
# Set session send buffer size & timeout.
session_send_bufsize = "64kb"
session_send_timeout = "30s"
# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.
# Set session pipeline buffer size.
session_max_pipeline = 10000
# Set session tcp keepalive period. (0 to disable)
session_keepalive_period = "75s"
# Set session to be sensitive to failures. Default is false, instead of closing socket, proxy will send an error response to client.
session_break_on_failure = false
# Set metrics server (such as http://localhost:28000), proxy will report json formatted metrics to specified server in a predefined period.
metrics_report_server = ""
metrics_report_period = "1s"
# Set influxdb server (such as http://localhost:8086), proxy will report metrics to influxdb.
metrics_report_influxdb_server = ""
metrics_report_influxdb_period = "1s"
metrics_report_influxdb_username = ""
metrics_report_influxdb_password = ""
metrics_report_influxdb_database = ""
# Set statsd server (such as localhost:8125), proxy will report metrics to statsd.
metrics_report_statsd_server = ""
metrics_report_statsd_period = "1s"
metrics_report_statsd_prefix = ""
編寫啟動腳本
start-proxy.sh
#!/bin/sh
#set -x
nohup ./codis-proxy --ncpu=4 --config=./config/proxy.toml --log=./logs/proxy.log --log-level=WARN &>/dev/null &
執行啟動腳本,然後通路
11080
端口可以檢視代理資訊。
codis-proxy 啟動後,處于 waiting 狀态,監聽 proxy_addr 位址,但是不會 accept 連接配接,添加到叢集并完成叢集狀态的同步,才能改變狀态為 online。添加的方法有以下兩種:
- 通過 codis-fe 添加:通過 Add Proxy 按鈕,将 admin_addr 加入到叢集中;
- 通過 codis-admin 指令行工具添加,方法如下:
$ ./codis-admin --dashboard=127.0.0.1:18080 --create-proxy -x 127.0.0.1:11080
其中 127.0.0.1:18080 以及 127.0.0.1:11080 分别為 dashboard 和 proxy 的
admin_addr
位址;
添加過程中,dashboard 會完成如下一系列動作:
- 擷取 proxy 資訊,對叢集 name 以及 auth 進行驗證,并将其資訊寫入到外部存儲中;
- 同步 slots 狀态;
- 标記 proxy 狀态為 online,此後 proxy 開始 accept 連接配接并開始提供服務;
啟動參數說明:
$ ./codis-proxy -h
Usage:
codis-proxy [--ncpu=N] [--config=CONF] [--log=FILE] [--log-level=LEVEL] [--host-admin=ADDR] [--host-proxy=ADDR] [--ulimit=NLIMIT]
codis-proxy --default-config
codis-proxy --version
Options:
--ncpu=N 最大使用 CPU 個數
-c CONF, --config=CONF 指定啟動配置檔案
-l FILE, --log=FILE 設定 log 輸出檔案
--log-level=LEVEL 設定 log 輸出等級:INFO,WARN,DEBUG,ERROR;預設INFO,推薦WARN
--ulimit=NLIMIT 檢查 ulimit -n 的結果,確定運作時最大檔案描述不少于 NLIMIT
預設配置檔案:
$ ./codis-proxy --default-config | tee proxy.toml
##################################################
# #
# Codis-Proxy #
# #
##################################################
# Set Codis Product {Name/Auth}.
product_name = "codis-demo"
product_auth = ""
# Set bind address for admin(rpc), tcp only.
admin_addr = "0.0.0.0:11080"
# Set bind address for proxy, proto_type can be "tcp", "tcp4", "tcp6", "unix" or "unixpacket".
proto_type = "tcp4"
proxy_addr = "0.0.0.0:19000"
# Set jodis address & session timeout.
jodis_addr = ""
jodis_timeout = 10
jodis_compatible = false
# Proxy will ping-pong backend redis periodly to keep-alive
backend_ping_period = 5
# If there is no request from client for a long time, the connection will be droped. Set 0 to disable.
session_max_timeout = 1800
# Buffer size for each client connection.
session_max_bufsize = 131072
# Number of buffered requests for each client connection.
# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.
session_max_pipeline = 1024
# Set period between keep alives. Set 0 to disable.
session_keepalive_period = 60
| product_name | 叢集名稱,參考 dashboard 參數說明|
| proto_type | Redis 端口類型,接受 tcp/tcp4/tcp6/unix/unixpacket |
| proxy_addr | Redis 端口位址或者路徑 |
| jodis_addr | Jodis 注冊 zookeeper 位址 |
| jodis_timeout | Jodis 注冊 session timeout 時間,機關 second |
| jodis_compatible | Jodis 注冊 zookeeper 的路徑 |
| backend_ping_period | 與 codis-server 探活周期,機關 second,0 表示禁止 |
| session_max_timeout | 與 client 連接配接最大讀逾時,機關 second,0 表示禁止 |
| session_max_bufsize | 與 client 連接配接讀寫緩沖區大小,機關 byte |
| session_max_pipeline | 與 client 連接配接最大的 pipeline 大小 |
| session_keepalive_period | 與 client 的 tcp keepalive 周期,僅 tcp 有效,0 表示禁止 |
注:Codis3 會将 jodis 節點注冊在 /jodis/{PRODUCT_NAME} 下,這點與 Codis2 不太相容,是以為了相容性,可以考慮将 jodis_compatible 設定成 true。
4.安裝codis-server(優化版的Redis)
codis-server的配置檔案和redis一樣,其本身就是在redis上改進而來。
建立配置檔案
config/codis-server/7001/redis.conf
bind 127.0.0.1
port 7001
daemonize no
pidfile /var/run/codis_7001.pid
logfile "./logs/codis-server/7001/redis.log"
save 900 1
save 300 10
save 60 10000
dir ./config/codis-server/7001
appendonly yes
appendfsync always
建立啟動腳本
start-server-7001.sh
#!/bin/sh
#set -x
nohup ./codis-server ./config/codis-server/7001/redis.conf &>/dev/null &
同樣的方法可以配置多個codis-server。
啟動完成後,可以通過 codis-fe 提供的界面或者 codis-admin 指令行工具添加到叢集中。
5.啟動codis-fe(叢集管理界面)
這是個可選元件,也可以通過codis-admin指令行工具來管理叢集。
start-fe.sh
#!/bin/sh
#set -x
nohup ./codis-fe --ncpu=1 --log=./logs/fe.log --log-level=WARN --zookeeper=zk1:2181,zk2:2182,zk3:2183 --listen=0.0.0.0:8090 &>/dev/null &
執行啟動腳本,然後通路8090端口即可看到叢集管理界面。
$ ./codis-fe -h
Usage:
codis-fe [--ncpu=N] [--log=FILE] [--log-level=LEVEL] [--assets-dir=PATH](--dashboard-list=FILE|--zookeeper=ADDR|--etcd=ADDR|--filesystem=ROOT) --listen=ADDR
codis-fe --version
Options:
--ncpu=N 最大使用 CPU 個數
-d LIST, --dashboard-list=LIST 配置檔案,能夠自動重新整理
-l FILE, --log=FILE 設定 log 輸出檔案
--log-level=LEVEL 設定 log 輸出等級:INFO,WARN,DEBUG,ERROR;預設INFO,推薦WARN
--listen=ADDR HTTP 服務端口
配置檔案 codis.json 可以手動編輯,也可以通過 codis-admin 從外部存儲中拉取,例如:
$ ./codis-admin --dashboard-list --zookeeper=127.0.0.1:2181 | tee codis.json
[
{
"name": "codis-demo",
"dashboard": "127.0.0.1:18080"
},
{
"name": "codis-demo2",
"dashboard": "127.0.0.1:28080"
}
]
6.使用codis-admin(叢集管理的指令行工具)
執行
./codis-admin -h
可以檢視可執行的指令及參數。
- dashboard服務和proxy服務的停用
./codis-admin --proxy=127.0.0.1:11080 --shutdown ./codis-admin --dashboard=127.0.0.1:18080 --shutdown
-
codis-dashboard 異常退出的修複
當 codis-dashboard 啟動時,會在外部存儲上存放一條資料,用于存儲 dashboard 資訊,同時作為 LOCK 存在。當 codis-dashboard 安全退出時,會主動删除該資料。當 codis-dashboard 異常退出時,由于之前 LOCK 未安全删除,重新開機往往會失敗。是以 codis-admin 提供了強制删除工具:
- 确認 codis-dashboard 程序已經退出(很重要);
- 運作 codis-admin 删除 LOCK:
./codis-admin --remove-lock --product=codis-demo --zookeeper=zk1:2181,zk2:2182,zk3:2183
-
codis-proxy 異常退出的修複
通常 codis-proxy 都是通過 codis-dashboard 進行移除,移除過程中 codis-dashboard 為了安全會向 codis-proxy 發送
指令,成功後才會将 proxy 資訊從外部存儲中移除。如果 codis-proxy 異常退出,該操作會失敗。此時可以使用 codis-admin 工具進行移除:offline
- 确認 codis-proxy 程序已經退出(很重要);
- 運作 codis-admin 删除 proxy:
選項$ ./codis-admin --dashboard=127.0.0.1:18080 --remove-proxy --addr=127.0.0.1:11080 --force
表示,無論--force
操作是否成功,都從外部存儲中将該節點删除。是以操作前,一定要确認該 codis-proxy 程序已經退出。offline
7.配置codis-ha
start-ha.sh
#!/bin/sh
#set -x
nohup ./codis-ha --log=./logs/ha.log --log-level=WARN --dashboard=127.0.0.1:18080 &>/dev/null &
因為 codis-proxy 是無狀态的,可以比較容易的搭多個執行個體,達到高可用性和橫向擴充。
對 Java 使用者來說,可以使用基于 Jedis 的實作
Jodis,來實作 proxy 層的 HA:
- 它會通過監控 zookeeper 上的注冊資訊來實時獲得目前可用的 proxy 清單,既可以保證高可用性;
- 也可以通過輪流請求所有的proxy實作負載均衡。
如果需要異步請求,可以使用基于Netty開發的
Nedis對下層的 redis 執行個體來說,當一個 group 的 master 挂掉的時候,應該讓管理者清楚,并手動的操作,因為這涉及到了資料一緻性等問題(redis的主從同步是最終一緻性的)。是以 codis 不會自動的将某個 slave 更新成 master。
關于外部 codis-ha 工具,這是一個通過 codis-dashboard 開放的 RESTful API 實作自動切換主從的工具。該工具會在檢測到 master 挂掉的時候主動應用主從切換政策,提升單個 slave 成為新的 master。
需要注意,codis 将其中一個 slave 更新為 master 時,該組内其他 slave 執行個體是不會自動改變狀态的,這些 slave 仍将試圖從舊的 master 上同步資料,因而會導緻組内新的 master 和其他 slave 之間的資料不一緻。是以當出現主從切換時,需要管理者手動建立新的 sync action 來完成新 master 與 slave 之間的資料同步(codis-ha 不提供自動操作的工具,因為這樣太不安全了)。
Codis使用
通路
http://IP:8090打開叢集管理,左側的菜單顯示了codis叢集清單。
添加組和sever
可以看到添加的三個codis-sever中7002是master,7001和7003是slave,這裡的主從關系不用在配置檔案中來配置主從關系,codis會自己配置主從,可以使用redis用戶端做個測試:
$ ./redis-cli -c -p 7002
127.0.0.1:7002> set k1 v1
OK
127.0.0.1:7002> set k2 v2
OK
127.0.0.1:7002> exit
$ ./redis-cli -c -p 7001
127.0.0.1:7001> get k1
"v1"
127.0.0.1:7001> get k2
"v2"
127.0.0.1:7001> set k3 v3
# (error) READONLY You can't write against a read only slave.
127.0.0.1:7001> exit
$ ./redis-cli -c -p 7003
127.0.0.1:7003> get k1
"v1"
127.0.0.1:7003> get k2
"v2"
127.0.0.1:7003> set k3 v3
# (error) READONLY You can't write against a read only slave.
127.0.0.1:7003> exit
可以看到隻能在master寫入,寫入的資料也同步到了slave上。此時去看7003和7001的配置檔案發現codis自動在配置檔案上加了
slaveof 127.0.0.1 7002
,假設此時master挂掉了
可以看到codis-ha自動将7003當成master,然後将7001和7002都停止了(程序不在),好危險,因為redis是最終一緻性,此時的資料一緻性也無法保證,而且将其他節點直接停止,此時的7003壓力将非常大。此時再将7001和7002重新開機,然後再次加入,發現codis會将這兩個執行個體再次停止,原因很簡單,因為原來7002是master,7001是7002的slave,配置并沒有變,不允許有兩個master,而且目前7003是master,是以需要手動更改配置檔案才能加入這個組。
假設現在沒有codis-ha,master 7003挂掉了會怎麼樣。
可以看到,并沒有将其他節點當成master的操作,此時重新開機7003就可以恢複目前組的叢集狀态,也不需要手動更改配置檔案和手動加入組。
添加proxy
設定Slots
使用redis用戶端連接配接proxy測試:
$ ./redis-cli -c -p 19000
127.0.0.1:19000> get k1
"v1"
127.0.0.1:19000> set k001 v001
OK
127.0.0.1:19000> get k001
"v001"
127.0.0.1:19000> exit
此時假設master 7003挂了(沒用codis-ha)會怎麼樣?
$ ./redis-cli -c -p 19000
127.0.0.1:19000> get k1
(error) ERR handle response, backend conn reset
127.0.0.1:19000> set k002 v002
(error) ERR handle response, backend conn reset
127.0.0.1:19000> exit
可以看到變成了既不可讀也不可寫了,這時啟動codis-ha繼續測試
codis-ha選擇了7001作為master,使用redis用戶端連接配接proxy測試:
$ ./redis-cli -c -p 19000
127.0.0.1:19000> get k1
"v1"
127.0.0.1:19000> get k001
"v001"
127.0.0.1:19000> set k0002 v0002
OK
127.0.0.1:19000> get k0002
"v0002"
127.0.0.1:19000> exit
可以看到目前是可以讀也可以寫的。