前言
閱讀本文需要具備docker涕蜂、docker-compose、redis等前置知識(shí)儲(chǔ)備阱洪。
centos版本:
cat /etc/redhat-release
CentOS Linux release 7.8.2003 (Core)
redis版本:
redis-server -v
Redis server v=6.0.8 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=75cef67090587c6
redis集群
Redis集群是Redis提供的分布式數(shù)據(jù)庫(kù)方案李根,集群通過(guò)分片(sharding)來(lái)進(jìn)行數(shù)據(jù)共享缓苛,并提供復(fù)制和故障轉(zhuǎn)移功能校摩。
Redis主從模式可以讀寫分離看峻;
Redis哨兵模式可以實(shí)現(xiàn)高可用的讀寫分離;
Redis集群模式則是在高可用的讀寫分離的基礎(chǔ)上再加上了數(shù)據(jù)分片衙吩。
以上只是個(gè)人對(duì)于Redis三種模式功能上總結(jié)互妓,實(shí)際上集群模式的數(shù)據(jù)存儲(chǔ)和故障轉(zhuǎn)移機(jī)制和哨兵模式并不一樣。
部署
目錄結(jié)構(gòu)
本文采用如下目錄結(jié)構(gòu):
.
|-- 7000.conf
|-- 7001.conf
|-- 7002.conf
|-- data
`-- docker-compose.yml
redis配置
準(zhǔn)備三個(gè)redis配置文件坤塞,端口分別是7000冯勉、7001和7002
7000.conf
# 監(jiān)聽(tīng)端口
port 7000
# 設(shè)定密碼認(rèn)證
requirepass 123456
# 開(kāi)啟集群配置
cluster-enabled yes
# 設(shè)定了保存節(jié)點(diǎn)配置文件的路徑,無(wú)需人為修改摹芙,Redis集群在啟動(dòng)時(shí)創(chuàng)建
cluster-config-file nodes.conf
# 節(jié)點(diǎn)連接超時(shí)配置
cluster-node-timeout 5000
appendonly yes
7001.conf
# 監(jiān)聽(tīng)端口
port 7001
# 設(shè)定密碼認(rèn)證
requirepass 123456
# 開(kāi)啟集群配置
cluster-enabled yes
# 設(shè)定了保存節(jié)點(diǎn)配置文件的路徑灼狰,無(wú)需人為修改,Redis集群在啟動(dòng)時(shí)創(chuàng)建
cluster-config-file nodes.conf
# 節(jié)點(diǎn)連接超時(shí)配置
cluster-node-timeout 5000
appendonly yes
7002.conf
# 監(jiān)聽(tīng)端口
port 7002
# 設(shè)定密碼認(rèn)證
requirepass 123456
# 開(kāi)啟集群配置
cluster-enabled yes
# 設(shè)定了保存節(jié)點(diǎn)配置文件的路徑浮禾,無(wú)需人為修改伏嗜,Redis集群在啟動(dòng)時(shí)創(chuàng)建
cluster-config-file nodes.conf
# 節(jié)點(diǎn)連接超時(shí)配置
cluster-node-timeout 5000
appendonly yes
docker-compose配置
用docker-compose來(lái)統(tǒng)一管理容器
docker-compose.yml
---
version: '3'
services:
# 7000的容器
node-1:
image: redis
container_name: node-1
restart: always
# 為了規(guī)避Docker中端口映射可能帶來(lái)的問(wèn)題
# 這里選擇使用host網(wǎng)絡(luò)
network_mode: host
# 指定時(shí)區(qū)坛悉,保證容器內(nèi)時(shí)間正確
environment:
TZ: "Asia/Shanghai"
volumes:
# 映射配置文件和數(shù)據(jù)目錄
- ./7000.conf:/usr/local/etc/redis/redis.conf
- ./data/7000:/data
sysctls:
# 必要的內(nèi)核參數(shù)
net.core.somaxconn: '511'
command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
# 7001的容器
node-2:
image: redis
container_name: node-2
restart: always
network_mode: host
environment:
TZ: "Asia/Shanghai"
volumes:
- ./7001.conf:/usr/local/etc/redis/redis.conf
- ./data/7001:/data
sysctls:
net.core.somaxconn: '511'
command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
# 7002的容器
node-3:
image: redis
container_name: node-3
restart: always
network_mode: host
environment:
TZ: "Asia/Shanghai"
volumes:
- ./7002.conf:/usr/local/etc/redis/redis.conf
- ./data/7002:/data
sysctls:
net.core.somaxconn: '511'
command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
啟動(dòng)、坑
后臺(tái)啟動(dòng)
docker-compose up -d
節(jié)點(diǎn)連接
這個(gè)時(shí)候?qū)嶋H上每個(gè)節(jié)點(diǎn)都是運(yùn)行一個(gè)獨(dú)立的集群當(dāng)中承绸,在7000節(jié)點(diǎn)中執(zhí)行cluster nodes命令:
可以看到當(dāng)前集群中只有7000節(jié)點(diǎn)自己。所以需要把他們連接起來(lái)挣轨,融合到一個(gè)集群中军熏,使用cluster meet命令可以完成這個(gè)工作:
cluster meet 127.0.0.1 7001
cluster meet 127.0.0.1 7002
再次查看cluster nodes
這就可以看到三個(gè)節(jié)點(diǎn)了
需要注意的是,這里雖然redis-server只用到了7000卷扮,7001和7002這三個(gè)端口荡澎,但實(shí)際上還會(huì)使用到17000,17001和17002三個(gè)端口晤锹,我就是因?yàn)閞edis部署在云端摩幔,安全組沒(méi)有放開(kāi)17000~17002這三個(gè)端口,所以在節(jié)點(diǎn)連接這里一直握手失敗鞭铆。
槽位指派
Redis集群通過(guò)分片的方式來(lái)保存數(shù)據(jù)庫(kù)中的鍵值對(duì):集群的整個(gè)數(shù)據(jù)庫(kù)被分為16384個(gè)槽(slot)或衡,數(shù)據(jù)庫(kù)中的每個(gè)鍵都屬于這16384個(gè)槽的其中一個(gè),集群中的每個(gè)節(jié)點(diǎn)可以處理0個(gè)或最多16384個(gè)槽车遂。
當(dāng)數(shù)據(jù)庫(kù)中的16384個(gè)槽都有節(jié)點(diǎn)在處理時(shí)封断,集群處于上線狀態(tài)(ok);相反地舶担,如果數(shù)據(jù)庫(kù)中有任何一個(gè)槽沒(méi)有得到處理坡疼,那么集群處于下線狀態(tài)(fail)。
參照書上的方法進(jìn)行槽位指派:
于是我進(jìn)行了如下各種命令組合的嘗試:
cluster addslots 0..5000
cluster addslots 0...5000
cluster addslots 0 .. 5000
cluster addslots 0 ... 5000
cluster addslots {0..5000}
cluster addslots {0...5000}
都沒(méi)有成功~衣陶,期待有大佬能教教我
折中方案
由于使用下面這些命令都不能正確執(zhí)行:
cluster addslots 0..5000
cluster addslots 0...5000
cluster addslots 0 .. 5000
cluster addslots 0 ... 5000
cluster addslots {0..5000}
cluster addslots {0...5000}
.........
感到絕望
不得已寫了個(gè)python腳本用于槽位分配
# -*- coding: utf-8 -*-
import redis
if __name__ == '__main__':
ip = input("請(qǐng)輸入IP:")
port = int(input("請(qǐng)輸入端口:"))
password = input("請(qǐng)輸入密碼:")
start_slot = int(input("請(qǐng)輸入開(kāi)始槽位號(hào):"))
end_slot = int(input("請(qǐng)輸入結(jié)束槽位號(hào):"))
# 拿到redis客戶端實(shí)例
r = redis.Redis(host=ip, port=port, password=password)
expect_num = end_slot - start_slot
actual_num = 0
for x in range(start_slot, end_slot + 1):
try:
result = r.execute_command("cluster addslots " + str(x))
if result == b'OK':
actual_num += 1
except redis.exceptions.ResponseError as e:
print("執(zhí)行 cluster addslots " + str(x) + " 失敱濉!")
if expect_num == actual_num:
print("所有槽位分配成功")
else:
print("部分槽位分配失敗")
集群狀態(tài)
腳本執(zhí)行成功以后再查看集群狀態(tài):
可以看到剪况,集群狀態(tài)已經(jīng)是上線狀態(tài)了
再看看槽位分配情況:
和我們預(yù)期結(jié)果一致
7000: 0~5000
7001: 5001~ 10000
7002: 10001~16383