上一篇文章描述了使用 Docker 基于哨兵模式搭建高可用的Redis绷耍,這一篇文章則使用Docker搭建Redis集群。
Redis Cluster 簡(jiǎn)介
Redis 3.0提供的分布式數(shù)據(jù)庫(kù)解決方案——Redis Cluster捏检。不僅可以主從復(fù)制轮傍,還可以像Sentinel那樣有故障轉(zhuǎn)移機(jī)制。除此之外,集群還有幾個(gè)獨(dú)有的特點(diǎn):去中心化和數(shù)據(jù)分片赡模。
去中心化:集群沒有中心(核心)節(jié)點(diǎn),就不會(huì)受到太大的影響师抄,當(dāng)某個(gè)主節(jié)點(diǎn)故障而不會(huì)影響整個(gè)集群的可用性漓柑。
分片:集群中的主節(jié)點(diǎn)可以水平擴(kuò)展,使用哈希槽將鍵值對(duì)分配到不同的主節(jié)點(diǎn)叨吮,分擔(dān)了單機(jī)Redis的壓力辆布。
接下來(lái)主要介紹如何使用 Docker 搭建Redis Cluster (Redis的版本為5.0)
1.創(chuàng)建集群目錄,存放各個(gè)節(jié)點(diǎn)的配置目錄(/conf/redis.conf)和數(shù)據(jù)目錄(/data)
for port in 'seq 8081 8089' ; do mkdir -p ./${port}/conf && PORT=${port} envsubst < ./redis-cluster.tmpl > ./${port}/conf/redis.conf && mkdir -p ./${port}/data; done
2.運(yùn)行端口為8081~8089的容器
for port in 'seq 8081 8089'; do docker run -d -ti -p ${port}:${port} -p 1${port}:1${port} -v /cluster-docker/${port}/conf/redis.conf:/etc/redis/redis.conf -v /cluster-docker/${port}/data:/data --restart always --name redis-${port} --net redis-net --sysctl net.core.somaxconn=1024 redis:5.0 redis-server /etc/redis/redis.conf; done
3.獲取各個(gè)容器的內(nèi)外ip
for port in 'seq 8081 8089'; do echo -n "$(docker inspect --format '{{ (index .NetworkSettings.Networks "bridge").IPAddress }}' "redis-${port}")":${port} ' ' ; done
復(fù)制打印出來(lái)的ip和端口
4.創(chuàng)建集群
隨便進(jìn)入一個(gè)redis容器茶鉴,譬如
docker exec -it redis-8081 /bin/bash
再執(zhí)行創(chuàng)建集群的命令
redis-cli --cluster create 172.17.0.2:8081 172.17.0.3:8082 172.17.0.4:8083 172.17.0.5:8084 172.17.0.6:8085 172.17.0.7:8086 172.17.0.8:8087 172.17.0.9:8088 172.17.0.10:8089 --cluster-replicas 2
需要特別說明的是 --cluster-replicas 2
這一條命令锋玲,表示集群中的每個(gè)主節(jié)點(diǎn)創(chuàng)建兩個(gè)從節(jié)點(diǎn)。示例的集群為三主六從
顯示 Can I set the above configuration? (type 'yes' to accept): 的時(shí)候涵叮,輸入yes
如無(wú)意外的話惭蹂,最后顯示 [OK] All 16384 slots covered. 則代表集群創(chuàng)建成功!如果輸入yes之后一直顯示 Waiting for the cluster to join...
請(qǐng)參考我另外一篇拙作 搭建Redis集群遇到的問題:Waiting for the cluster to join...
執(zhí)行cluster nodes
查看主從節(jié)點(diǎn)詳細(xì)信息割粮,如下圖:
輸出格式為:
<id> <ip:port> <flags> <master> <ping-sent> <pong-recv> <config-epoch> <link-state> <slot> <slot> ... <slot>
id
:節(jié)點(diǎn) ID盾碗。一個(gè)40個(gè)字符的隨機(jī)字符串,當(dāng)一個(gè)節(jié)點(diǎn)被創(chuàng)建時(shí)不會(huì)再發(fā)生變化(除非CLUSTER RESET HARD被使用)舀瓢。
ip:port
:客戶端應(yīng)該聯(lián)系節(jié)點(diǎn)以運(yùn)行查詢的節(jié)點(diǎn)地址廷雅。
flags
:逗號(hào)列表分隔的標(biāo)志:myself,master,slave榜轿,fail幽歼,handshake,noaddr谬盐,noflags甸私。
master
:如果節(jié)點(diǎn)是從屬節(jié)點(diǎn),并且主節(jié)點(diǎn)已知飞傀,則節(jié)點(diǎn)ID為主節(jié)點(diǎn)皇型,否則為“ - ”字符。
ping-sent
:以毫秒為單位的當(dāng)前激活的ping發(fā)送的unix時(shí)間砸烦,如果沒有掛起的ping弃鸦,則為零。
pong-recv
:毫秒 unix 時(shí)間收到最后一個(gè)ping幢痘。
config-epoch
:當(dāng)前節(jié)點(diǎn)(或當(dāng)前主節(jié)點(diǎn)唬格,如果該節(jié)點(diǎn)是從節(jié)點(diǎn))的配置時(shí)期(或版本)。每次發(fā)生故障切換時(shí)颜说,都會(huì)創(chuàng)建一個(gè)新的购岗,唯一的,單調(diào)遞增的配置時(shí)期门粪。如果多個(gè)節(jié)點(diǎn)聲稱服務(wù)于相同的哈希槽喊积,則具有較高配置時(shí)期的節(jié)點(diǎn)將獲勝。
link-state
:用于節(jié)點(diǎn)到節(jié)點(diǎn)集群總線的鏈路狀態(tài)玄妈。我們使用此鏈接與節(jié)點(diǎn)進(jìn)行通信乾吻。可以是connected或disconnected拟蜻。
slot
:散列槽號(hào)或范圍绎签。從參數(shù)9開始,但總共可能有16384個(gè)條目(限制從未達(dá)到)瞭郑。這是此節(jié)點(diǎn)提供的散列槽列表辜御。如果條目?jī)H僅是一個(gè)數(shù)字鸭你,則被解析為這樣屈张。如果它是一個(gè)范圍,它是在形式start-end袱巨,并且意味著節(jié)點(diǎn)負(fù)責(zé)所有散列時(shí)隙從start到end包括起始和結(jié)束值阁谆。
模擬主節(jié)點(diǎn)故障
模擬端口為8082的主節(jié)點(diǎn)發(fā)送故障,執(zhí)行 docker stop redis-8082
后再次進(jìn)入端口為8081的節(jié)點(diǎn)查看集群信息愉老〕÷蹋可以看到端口為8082的節(jié)點(diǎn)的flag
標(biāo)志為:master,fail;link-state
為disconnected嫉入。再看端口為8088的節(jié)點(diǎn)變?yōu)橹鞴?jié)點(diǎn)焰盗,因此可以判斷原先端口為8082的主節(jié)點(diǎn)下線后璧尸,故障轉(zhuǎn)移由其從節(jié)點(diǎn)替代。
此時(shí)我再執(zhí)行 docker start redis-8082
熬拒,可以發(fā)現(xiàn)端口為8082的服務(wù)在集群中connect爷光,而且成為端口8088的從節(jié)點(diǎn)。
總結(jié)
以上就是使用Docker容器的技術(shù)搭建Redis集群澎粟,主要描述了Redis集群搭建的過程和模擬故障轉(zhuǎn)移的實(shí)踐蛀序。具體Redis命令背后的原理和詳細(xì)的執(zhí)行過程,推薦閱讀黃健宏老師寫的《Redis 設(shè)計(jì)與實(shí)現(xiàn)》活烙,個(gè)人感覺寫的十分通俗易懂徐裸,給了我很多啟示!
參考資料:
https://cloud.tencent.com/developer/section/1374002
《Redis 設(shè)計(jì)與實(shí)現(xiàn)》