docker redis 集羣搭建
本教程使用官方redis 鏡像+docker-compose 完成整個redis集羣的搭建,之所以使用docker-compose 是因爲只需要寫好配置文件部署執行方便
省略步驟
請參考docker官方文檔
-
docker 安裝
-
docker compose 安裝
正式開始
說白了都是配置文件
爲了下面不迷路,先把配置的目錄結構貼上 不要急着建目錄結構,大多目錄後面我有腳本直接生成,下面高亮的爲目錄:
redis-cluster
-data
--7000
----conf
----data
----logs
--7001
----conf
----data
----logs
--7002
----conf
----data
----logs
--7003
----conf
----data
----logs
--7004
----conf
----data
----logs
--7005
----conf
----data
----logs
--redis-cluster.tmpl
--docker-compose.yml
好了,以上就是這次集羣的目錄結構,解釋一下:
redis-cluster 目錄不用說了是我們工作空間
data 目錄是所有redis 節點配置文件所以在目錄
data 目錄下的700x 目錄是針對單個節點的配置所在目錄,至於700x 是redis 服務的端口。端口目錄下的 conf 目錄下存了當前redis 節點的真實配置文件。至於端口下的data目錄是我docker volume 映射的目錄,這個當然你隨便。
redis-cluster.tmpl 爲redis 節點的模板文件
至於docker-compose.yml 文件就不必說了這個是docker-compose 啓動服務的配置文件
-
首先新建了一個工作目錄 redis-cluster
由於我實現redis 集羣用了6臺redis 節點 ,每臺都要寫配置文件總不方便
所以
首先爲redis 配置文件文件創建了一個模板 我命名爲 redis-cluster.tmpl 以下內容:
##節點端口
port ${PORT}
##開啓集羣模式
protected-mode no
##cluster集羣模式
cluster-enabled yes
##集羣配置名
cluster-config-file nodes.conf
##超時時間
cluster-node-timeout 5000
##實際爲各節點網卡分配ip
cluster-announce-ip 172.19.0.${IPEND}
##節點映射端口
cluster-announce-port ${PORT}
##節點總線端口
cluster-announce-bus-port 1${PORT}
##持久化模式
appendonly yes
這裏有個配置需要解釋一下:cluster-announce-ip 這個參數的值 172.19.0.${IPEND} 不是我隨便寫的,這個是取自docker service 使用的network 的網關地址。如果你無法確定 請使用
`docker inspect <network-name>
查看。
-
生成配置
使用上面模板加上如下腳本來生成我們需要的redis 各個節點的目錄和配置,你可以把下面腳本寫進xx.sh 文件放到redis-cluster 工作空間執行
#!/bin/bash for port in `seq 7000 7005`; do mkdir -p ./data/${port}/conf && PORT=${port} IPEND=17${port:0-1:1} envsubst < ./redis-cluster.tmpl > ./data/${port}/conf/redis.conf && mkdir -p ./data/${port}/data; done
到此開始我們展示的目錄及除了 docker-compose.yml 文件都已經全了
-
寫 docker-compose.yml 文件
version: '3' services: redis-7000: image: redis:latest container_name: redis-7000 volumes: - ./data/7000/conf/redis.conf:/usr/local/etc/redis/redis.conf - ./data/7000/data:/data - ./data/7000/logs:/usr/local/redis/logs command: redis-server /usr/local/etc/redis/redis.conf --requirepass yasin ports: - "7000:7000" - "17000:17000" restart: always networks: redis-net: ipv4_address: 172.19.0.170 logging: driver: "json-file" options: max-size: "1m" redis-7001: image: redis:latest container_name: redis-7001 volumes: - ./data/7001/conf/redis.conf:/usr/local/etc/redis/redis.conf - ./data/7001/data:/data - ./data/7001/logs:/usr/local/redis/logs command: redis-server /usr/local/etc/redis/redis.conf --requirepass yasin ports: - "7001:7001" - "17001:17001" restart: always networks: redis-net: ipv4_address: 172.19.0.171 logging: driver: "json-file" options: max-size: "1m" redis-7002: image: redis:latest container_name: redis-7002 volumes: - ./data/7002/conf/redis.conf:/usr/local/etc/redis/redis.conf - ./data/7002/data:/data - ./data/7002/logs:/usr/local/redis/logs command: redis-server /usr/local/etc/redis/redis.conf --requirepass yasin ports: - "7002:7002" - "17002:17002" restart: always networks: redis-net: ipv4_address: 172.19.0.172 logging: driver: "json-file" options: max-size: "1m" redis-7003: image: redis:latest container_name: redis-7003 volumes: - ./data/7003/conf/redis.conf:/usr/local/etc/redis/redis.conf - ./data/7003/data:/data - ./data/7003/logs:/usr/local/redis/logs command: redis-server /usr/local/etc/redis/redis.conf --requirepass yasin ports: - "7003:7003" - "17003:17003" restart: always networks: redis-net: ipv4_address: 172.19.0.173 logging: driver: "json-file" options: max-size: "1m" redis-7004: image: redis:latest container_name: redis-7004 volumes: - ./data/7004/conf/redis.conf:/usr/local/etc/redis/redis.conf - ./data/7004/data:/data - ./data/7004/logs:/usr/local/redis/logs command: redis-server /usr/local/etc/redis/redis.conf --requirepass yasin ports: - "7004:7004" - "17004:17004" restart: always networks: redis-net: ipv4_address: 172.19.0.174 logging: driver: "json-file" options: max-size: "1m" redis-7005: image: redis:latest container_name: redis-7005 volumes: - ./data/7005/conf/redis.conf:/usr/local/etc/redis/redis.conf - ./data/7005/data:/data - ./data/7005/logs:/usr/local/redis/logs command: redis-server /usr/local/etc/redis/redis.conf --requirepass yasin ports: - "7005:7005" - "17005:17005" restart: always networks: redis-net: ipv4_address: 172.19.0.175 logging: driver: "json-file" options: max-size: "1m" networks: redis-net: external: true
-
--requirepass yasin 這個是我爲每個redis node 設置了 密碼 yasin ,不需要可以去掉。
ipv4_address 這裏的ip地址一定要與redis.conf 中的地址一致.
external: true 這裏external 值爲true 是我事前創建了
docker network create --driver bridge redis-net
如果是Windows 機器可能會失敗 可以再嘗試docker network create --driver nat redis-net
-
創建並啓動容器
好了,配置文件準備就緒就讓我們看一下效果吧,在我們的工作空間下執行以下命令來創建我們的6臺 docker redis 服務:
docker-compose up
-
組建集羣
服務起來之後剩下的事情就是讓6臺redis 感知到彼此,進入到其中一臺容器
docker exec -it redis-7000 bash
(容器內執行)
for N in `seq 0 5` ; do
redis-cli -h 172.19.0.170 -p 7000 -a yasin cluster meet 172.19.0.17${N} 700${N};
done
teps: 我在執行到這一步的時候吃了大虧,按理說只要一臺節點去感知了其他節點其他節點都會自動相互感知,但是當時執行到這一步時,沒有執行上面命令的節點死活感知不到其他節點。問題在於reds 的配置文件裏我把 cluster-announce-ip 172.19.0.${IPEND} 寫死爲 cluster-announce-ip 0.0.0.0 導致其他節點一直在執行 :
cluster meet 0.0.0.0 7000
cluster meet 0.0.0.0 7001
cluster meet 0.0.0.0 7002
cluster meet 0.0.0.0 7003
cluster meet 0.0.0.0 7004
cluster meet 0.0.0.0 7005
其中一臺節點怎麼可能同時用於700x的所有redis 端口呢!
檢查一下所有節點是否都感知到了彼此:在每臺節點執行如下命令 打印出6臺節點的信息記錄下每行的id (節點標識),很重要下面要用
(容器內執行)
redis-cli -h 172.19.0.170 -p 7000 -a yasin cluster nodes
到此redis 集羣搭建完成
-
分配槽點
6 個節點,我們選出端口爲7000、7001、7002 三臺爲master 節點 ,並且爲他們分配槽點
(容器內執行)
redis-cli -h 172.19.0.170 -p 7000 -a yasin CLUSTER ADDSLOTS {0,5461}
redis-cli -h 172.19.0.171 -p 7001 -a yasin CLUSTER ADDSLOTS {5462,10922}
redis-cli -h 172.19.0.171 -p 7001 -a yasin CLUSTER ADDSLOTS {10923,16383}
-
分配slave
(容器內執行) 這裏就用到了上面記錄的 節點標識
# 此命令是在 從redis節點內執行 關聯到 主redis 的節點標識
# 主 redis-7000 從 redis-7003
/usr/local/bin/redis-cli -h 172.19.0.173 -p 7003 -a yasin CLUSTER REPLICATE 5631cd7205b964c0c848ddc7292835fa8a4df57c
# 主 redis-7001 從 redis-7004
/usr/local/bin/redis-cli -h 172.19.0.174 -p 7004 -a yasin CLUSTER REPLICATE d0423573bfe628fb03cee2feead667ef5679c17d
# 主 redis-7002 從 redis-7005
/usr/local/bin/redis-cli -h 172.19.0.175 -p 7005 -a yasin CLUSTER REPLICATE 8563d43bf400b6435a921f4783420cca02fa2d5a
-
集羣密碼
如果需要可以爲集羣設置密碼(容器內執行 密碼yasin
for n in `seq 0 5` ; do
# 爲每個節點設相同密碼
redis-cli -h 172.19.0.17${n} -p 700${n} -a yasin config set requirepass yasin;
# 爲slave節點設置主節點的密碼,可能用於同步主節點數據驗證使用(我這裏爲所有節點都設置了)
redis-cli -h 172.19.0.17${n} -p 700${n} -a yasin config set masterauth yasin;
done
-
驗證、結束
到目前redis cluster 搭建結束,試一下集羣連接 注意命令中的 -c
是用於連接集羣的。
redis-cli -h -c 172.19.0.170 -p 7000 -a yasin set name 張三
for n in `seq 0 5` ; do
redis-cli -h -c 172.19.0.17${n} -p 700${n} -a yasin get name 張三
done