天天看點

從零開始:手把手教你搭建 Redis Cluster 高可用叢集

從零開始:手把手教你搭建 Redis Cluster 高可用叢集

前言

當今網際網路領域中,高并發、高可用已經成為了開發人員必須要面對的挑戰。作為一款優秀的分布式記憶體資料庫,Redis 在這方面表現得相當出色。然而,為了滿足大規模應用程式的需求,單節點 Redis 已經無法滿足要求,是以需要搭建 Redis Cluster 叢集來實作高可用性、高擴充性和高性能的目标。在本文中,我們将詳細講解如何搭建 Redis Cluster 叢集,并分享一些實踐經驗和注意事項,幫助讀者了解 Redis Cluster 叢集的設計原理和使用方法,進而更好地應對高并發場景下的挑戰。

Redis 叢集說明

Redis 叢集主要有以下幾種:Redis Cluster(Redis叢集模式),Redis Sentinel(Redis哨兵模式),Redis分片(Sharding)+複制(Replication)(這是一種手動實作的方式,通過将資料分片存儲在多個Redis執行個體上,每個執行個體負責管理部分資料,并使用複制機制在執行個體之間同步資料)。

本文搭建的是Redis Cluster 叢集,Redis官方提供的分布式解決方案,從Redis 3.0版本開始引入。它通過分片(sharding)和複制(replication)來實作高可用性和擴充性。Redis Cluster将資料分散存儲在多個節點上,每個節點負責管理部分資料,并在需要時進行資料複制,以提供故障恢複和負載均衡。

Redis Cluster叢集使用的插槽算法是一緻性雜湊演算法,Redis Cluser采用虛拟槽分區,所有的鍵根據哈希函數映射到0~16383個整數槽内,計算公式:slot=CRC16(key)&16383。

由于采用高品質的雜湊演算法,每個槽所映射的資料通常比較均勻。

從零開始:手把手教你搭建 Redis Cluster 高可用叢集

環境

  • 很久之前工作中淘汰三台實體小主機,系統為Centos7.6
  • Docker版本 24.0.2
  • Redis版本 6.2.6
從零開始:手把手教你搭建 Redis Cluster 高可用叢集
從零開始:手把手教你搭建 Redis Cluster 高可用叢集
從零開始:手把手教你搭建 Redis Cluster 高可用叢集

本人打算在每台實體機上分别搭建兩個節點,一共六個節點組成3對Master--Slave,即 3個Master 3個Slave。

開始行動

  1. 拉取redis鏡像
docker search redis 
docker pull redis           

直接docker pull redis 将會拉取redis 最新鏡像,可以按需拉取自己所需版本。

docker images 檢視本地鏡像           
從零開始:手把手教你搭建 Redis Cluster 高可用叢集
  1. 在每台實體機上建立虛拟網絡,供每台實體機上的docker虛拟主機之間通信。
docker network create redis-net 建立網絡 
docker network ls 檢視網絡           
從零開始:手把手教你搭建 Redis Cluster 高可用叢集
  1. 編寫shell腳本,生成redis.conf 配置檔案
ip=`ifconfig enp2s0 |grep "inet " |awk '{print $2}'`
for port in $(seq 6379 6380);
do
mkdir -p ./node-${port}/conf
touch ./node-${port}/conf/redis.conf
cat  << EOF > ./node-${port}/conf/redis.conf
port ${port}
requirepass 123
bind 0.0.0.0
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes 
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip ${ip} 
cluster-announce-port ${port}
cluster-announce-bus-port 1${port}
EOF
done           

配置參數說明:

  • port:節點端口;
  • requirepass:設定密碼,通路時需要驗證
  • protected-mode:保護模式,預設值 yes,即開啟。開啟保護模式以後,需配置bind ip 或者設定通路密碼;關閉保護模式,外部網絡可以直接通路;
  • daemonize:是否以守護線程的方式啟動(背景啟動),預設 no;
  • appendonly:是否開啟 AOF 持久化模式,預設 no;
  • cluster-enabled:是否開啟叢集模式,預設 no;
  • cluster-config-file:叢集節點資訊檔案;
  • cluster-node-timeout:叢集節點連接配接逾時時間;
  • cluster-announce-ip:叢集節點 IP
    • 注意: 如果你想要你的redis叢集可以供外網通路,這裡直接填 伺服器的IP 位址即可
    • 如若為了安全,隻是在伺服器内部進行通路,這裡還需要做一些修改。
  • cluster-announce-port:叢集節點映射端口;
  • cluster-announce-bus-port:叢集節點總線端口,内部節點之間通信所需的TCP端口。

因為本人有三台實體機,對應的内網IP分别是 192.168.0.200,192.168.0.201,192.168.0.202,是以設定 cluster-announce-ip 參數時需動态擷取每台實體機的IP,每台機器上啟動兩個節點,對應的端口分别是6379和6380,Redis 預設規定内部節點通信端口為節點端口+10000即16379和16380。在每台實體機上執行以上腳本,會在目前項目目錄下生成兩個節點檔案夾,此檔案夾是redis配置檔案和資料的存放目錄,在運作docker容器時會映射到虛拟機裡。

從零開始:手把手教你搭建 Redis Cluster 高可用叢集
  1. 編寫shell腳本,啟動容器
ip=`ifconfig enp2s0 |grep "inet " |awk '{print $2}'|cut -c 11-`
for port in $(seq 6379 6380)
do
        docker run -it -d -p ${port}:${port} -p 1${port}:1${port} \
        --privileged=true -v ./node-${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \
        --privileged=true -v ./node-${port}/data:/data \
        --restart always --name redis_${ip}_${port} --net redis-net \
        --sysctl net.core.somaxconn=1024 redis redis-server /usr/local/etc/redis/redis.conf
done;           

docker 啟動時的參數不做過多說明,為了區分6個節點,在容器命名時加入了伺服器IP的後半段,命名規則是:redis_${ip}_${port}

ip=`ifconfig enp2s0 |grep "inet " |awk '{print $2}'|cut -c 11-`            

截取到目前伺服器iP的後半段,比如192.168.0.200 的ip擷取到的就是200

在每台機器上執行以上腳本,即可啟動容器。

從零開始:手把手教你搭建 Redis Cluster 高可用叢集
  1. 開始建立Redis Cluster叢集

随便進入到一個節點容器中

docker exec -it redis_201_6379 bash           

執行

redis-cli -a 123 --cluster create 192.168.0.201:6379 192.168.0.201:6380 192.168.0.200:6379 192.168.0.200:6380 192.168.0.202:6379 192.168.0.202:6380 --cluster-replicas 1           

-a 後面為目前節點設定的密碼,直接用此參數會有一個警告,是因為在指令行直接使用銘文密碼,會在曆史記錄中暴露密碼,導緻不安全行為發生,但不影響指令執行。

Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe

執行後出現下圖代表 成功:

從零開始:手把手教你搭建 Redis Cluster 高可用叢集

插槽會均勻分布在各個節點上。進入任意節點檢視叢集狀态資訊:

檢視節點資訊在

  1. 指令行測試

以叢集方式登入redis_202_6379 節點:

redis-cli -c -a 123 set k1 tie           

同樣的方式登入redis_202_6380節點:

redis-cli -c -p 6380 -a 123 get k1           

得到如下結果:

從零開始:手把手教你搭建 Redis Cluster 高可用叢集
  1. 代碼測試

建立Golang腳本

package main

import (
	"fmt"
	"github.com/go-redis/redis/v8"
	"golang.org/x/net/context"
	"time"
)

var clusterClient *redis.ClusterClient

func init() {
	// 連接配接redis叢集
	ctx := context.Background()
	clusterClient = redis.NewClusterClient(&redis.ClusterOptions{
		Addrs: []string{ // 填寫master主機
			"192.168.0.200:6379",
			"192.168.0.201:6379",
			"192.168.0.202:6379",
		},
		Password:     "123",                 // 設定密碼
		DialTimeout:  50 * time.Microsecond, // 設定連接配接逾時
		ReadTimeout:  50 * time.Microsecond, // 設定讀取逾時
		WriteTimeout: 50 * time.Microsecond, // 設定寫入逾時
	})
	// 發送一個ping指令,測試是否通
	s := clusterClient.Do(ctx, "ping").String()
	fmt.Println(s)
}
func main() {
	ctx := context.Background()
	err := clusterClient.Set(ctx, "k1", "tiesheng", 0).Err()
	if err != nil {

		panic(err)
	}
	getValue := clusterClient.Get(ctx, "k1")
	fmt.Println(getValue.Val(), getValue.Err())
}
           

執行得到如下結果:

從零開始:手把手教你搭建 Redis Cluster 高可用叢集

到此 ,已經大功告成了!!

後期随着業務量的增加,可以動态對叢集進行擴容

# 将192.168.0.200:6381節點添加到192.168.0.200:6379節點所在的叢集中
redis-cli --cluster add-node 192.168.0.200:6381 192.168.0.200:6379

#  将192.168.0.200:6382 節點添加到192.168.0.200:6379 對應的叢集中,并且加入的節點為從節點,
#  對應的主節點 id是e0b5798ead8281982053f952d3f2605c2818a0e8
redis-cli --cluster add-node 192.168.0.200:6382 192.168.0.200:6379 --cluster-slave --cluster-master-id e0b5798ead8281982053f952d3f2605c2818a0e8           

節點Id可以通過指令 Cluster nodes 檢視。

go實作CRC16

package main

import (
    "fmt"
    "hash/crc32"
)

func crc16(data []byte) uint16 {
    crcTable := crc32.MakeTable(0x8005) // CRC-16-IBM

    // 使用CRC32計算得到32位的校驗值
    crc := crc32.Checksum(data, crcTable)

    // 取校驗值的低16位作為CRC16校驗值
    crc16 := uint16(crc & 0xffff)
    return crc16
}

func main() {
    data := []byte("hello world")
    result := crc16(data)
    fmt.Printf("CRC16: 0x%04x\n", result)
}
           

繼續閱讀