Docker部署Redis集群-小白入門

前言

閱讀本文需要具備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
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命令:


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


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)。

下線狀態(tài)

參照書(shū)上的方法進(jìn)行槽位指派:


image.png

于是我進(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):


cluster info

可以看到,集群狀態(tài)已經(jīng)是上線狀態(tài)了

再看看槽位分配情況:


cluster slots

和我們預(yù)期結(jié)果一致

7000: 0~5000
7001: 5001~ 10000
7002: 10001~16383

參考文章

槽指派
Redis 集群教程

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容