redis cluster三主三从搭建

redis cluster三主三从搭建

分了原生部署和docker部署
说实话,redis的cluster三主三从是不合理的,cluster最少需要三台服务器,一万多个卡槽分配在这三台机器上,当有一台挂了,就会有三份之一的数据不可用,所以一般需要多台机器,分成多份,即使挂了一台,也会只影响其中这台机器上的卡槽的数据。我们要做的就是新家一台,把旧的那台下掉,重新分配下数据就可以了

三主三从,三台机器上有6个端口,供应用使用,此外还有6个心跳检测端口
如6379 *3 7379 *3, 16379 *3 17379 *3

前言

redis cluster的自我介绍:

1、redis cluster是Redis的分布式解决方案,在3.0版本推出后有效地解决了redis分布式方面的需求

2、自动将数据进行分片,每个master上放一部分数据

3、提供内置的高可用支持,部分master不可用时,还是可以继续工作的

4、支撑N个redis master node,每个master node都可以挂载多个slave node

5、高可用:因为每个master都有salve节点,那么如果mater挂掉,redis cluster这套机制,就会自动将某个slave切换成master

redis cluster的hash slot(哈希槽)算法:

1、redis cluster有固定的16384个hash slot,对每个key计算CRC16值,然后对16384取模,可以获取key对应的hash slot

2、redis cluster中每个master都会持有部分slot,比如有3个master,那么可能每个master持有5000多个hash slot

3、hash slot让node的增加和移除很简单,增加一个master,就将其他master的hash slot移动部分过去,减少一个master,就将它的hash slot移动到其他master上去

4、移动hash slot的成本是非常低的

5、客户端的api,可以对指定的数据,让他们走同一个hash slot,通过hash tag来实现

6、127.0.0.1:7000>CLUSTER ADDSLOTS 0 1 2 3 4 ... 5000 可以将槽0-5000指派给节点7000负责。

7、每个节点都会记录哪些槽指派给了自己,哪些槽指派给了其他节点。

8、客户端向节点发送键命令,节点要计算这个键属于哪个槽。

9、如果是自己负责这个槽,那么直接执行命令,如果不是,向客户端返回一个MOVED错误,指引客户端转向正确的节点。

redis cluster 多master的写入:

1、在redis cluster写入数据的时候,其实是你可以将请求发送到任意一个master上去执行

2、每个master都会计算这个key对应的CRC16值,然后对16384个hashslot取模,找到key对应的hashslot,找到hashslot对应的master

3、如果对应的master就在自己本地的话,set mykey1 v1,mykey1这个key对应的hashslot就在自己本地,那么自己就处理掉了

4、如果计算出来的hashslot在其他master上,那么就会给客户端返回一个moved error,告诉你,你得到哪个master上去执行这条写入的命令

5、什么叫做多master的写入,就是每条数据只能存在于一个master上,不同的master负责存储不同的数据,分布式的数据存储

100w条数据,5个master,每个master就负责存储20w条数据,分布式数据存储

6、默认情况下,redis cluster的核心的理念,主要是用slave做高可用的,每个master挂一两个slave,主要是做数据的热备,还有master故障时的主备切换,实现高可用的

7、redis cluster默认是不支持slave节点读或者写的,跟我们手动基于replication搭建的主从架构不一样的

8、jedis客户端,对redis cluster的读写分离支持不太好的

9、默认的话就是读和写都到master上去执行的

10、如果你要让最流行的jedis做redis cluster的读写分离的访问,那可能还得自己修改一点jedis的源码,成本比较高

11、读写分离,是为了什么,主要是因为要建立一主多从的架构,才能横向任意扩展slave node去支撑更大的读吞吐量

12、redis cluster的架构下,实际上本身master就是可以任意扩展的,你如果要支撑更大的读吞吐量,或者写吞吐量,或者数据量,都可以直接对master进行横向扩展就可以了

节点间的内部通信机制:

1、基础通信原理

(1)redis cluster节点间采取gossip协议进行通信

  跟集中式不同,不是将集群元数据(节点信息,故障,等等)集中存储在某个节点上,而是互相之间不断通信,保持整个集群所有节点的数据是完整的

  集中式:好处在于,元数据的更新和读取,时效性非常好,一旦元数据出现了变更,立即就更新到集中式的存储中,其他节点读取的时候立即就可以感知到; 不好在于,所有的元数据的跟新压力全部集中在一个地方,可能会导致元数据的存储有压力

  gossip:好处在于,元数据的更新比较分散,不是集中在一个地方,更新请求会陆陆续续,打到所有节点上去更新,有一定的延时,降低了压力; 缺点,元数据更新有延时,可能导致集群的一些操作会有一些滞后

(2)10000端口

  每个节点都有一个专门用于节点间通信的端口,就是自己提供服务的端口号+10000,比如7001,那么用于节点间通信的就是17001端口

  每隔节点每隔一段时间都会往另外几个节点发送ping消息,同时其他几点接收到ping之后返回pong

(3)交换的信息

  故障信息,节点的增加和移除,hash slot信息,等等

gossip协议

  gossip协议包含多种消息,包括ping,pong,meet,fail,等等

  meet: 某个节点发送meet给新加入的节点,让新节点加入集群中,然后新节点就会开始与其他节点进行通信

  redis-trib.rb add-node

  其实内部就是发送了一个gossip meet消息,给新加入的节点,通知那个节点去加入我们的集群

  ping: 每个节点都会频繁给其他节点发送ping,其中包含自己的状态还有自己维护的集群元数据,互相通过ping交换元数据

  每个节点每秒都会频繁发送ping给其他的集群,ping,频繁的互相之间交换数据,互相进行元数据的更新

  pong: 返回ping和meet,包含自己的状态和其他信息,也可以用于信息广播和更新

  fail: 某个节点判断另一个节点fail之后,就发送fail给其他节点,通知其他节点,指定的节点宕机了

原生部署cluster集群

需要用到三台机器,每台机器上启动8001和8002端口,也可以根据自己需求改成别的端口,在下面配置文件中会体现

安装C/C++环境

Redis编译时需要使用C/C++环境:

yum install -y gcc gcc-c++ make

redis下载

wget https://download.redis.io/releases/redis-5.0.13.tar.gz

解压、编译

//依赖库安装
yum install gcc gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel -y

tar -zxvf redis-5.0.13.tar.gz
cd redis-5.0.13
make

创建Redis相关工作目录(目录可自定义)

mkdir /data/redis/redis-cluster/{data/{redis_8001,redis_8002},conf,log} -p

复制redis配置文件

cp /data/redis/redis-5.0.13/redis.conf /data/redis/redis-cluster/conf/redis_8001.conf
cp /data/redis/redis-5.0.13/redis.conf /data/redis/redis-cluster/conf/redis_8002.conf

修改Redis配置文件

    port 8001             
	#修改redis监听端口(可以自定义) 8001与端口号同步
	bind 0.0.0.0            
	#表示redis允许所有地址连接。默认127.0.0.1,仅允许本地连接。
	daemonize yes             
	#允许redis后台运行
	pidfile /var/run/redis_8001.pid     
	#pid存放目录 8001与端口号同步
	logfile "/data/redis/redis-cluster/log/redis_8001.log"   
	#设置日志存放路径 8001与端口号同步
	dir /data/redis/redis-cluster/data/redis_8001  
	#工作目录 8001与端口号同步
	cluster-enabled yes     
	#是否开启集群
	cluster-config-file /data/redis/redis-cluster/conf/nodes_8001.conf
	#集群配置文件的名称,每个节点都有一个集群相关的配置文件,持久化保存集群的信息  8001与端口号同步
	#这个文件并不需要手动配置,这个配置文件有Redis生成并更新, 
	cluster-node-timeout 15000
	#节点互连超时的阀值。集群节点超时毫秒数,默认15秒
	appendonly yes
	#Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件, 
	#每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。
	appendfsync everysec
	#Redis会把每次写入的数据在接收后每秒写入一次 appendonly.aof 文件
	requirepass 123456    
	#设置redis密码
	masterauth 123456    
	#主从同步master的密码(如果没有设置redis密码,则无需配置)

启动Redis

集群内每台服务器分别启动两个redis

cd /data/redis/redis-5.0.13/src/
./redis-server /data/redis/redis-cluster/conf/redis_8001.conf
./redis-server /data/redis/redis-cluster/conf/redis_8002.conf

创建Redis Cluster

./redis-cli -a  {redis密码} --cluster create {redis集群地址} --cluster-replicas 1

例子: ./redis-cli -a 123456 --cluster create 192.168.48.91:8001 192.168.48.91:8002 192.168.48.92:8001 192.168.48.92:8002 192.168.48.93:8001  192.168.48.93:8002--cluster-replicas 1

验证集群Redis-Cluster

//登录redis集群
./redis-cli -a {redis密码} -h {redis地址} -p {redsi端口} -c
//验证集群信息
{redis地址}:{redis端口}>cluster info #查看集群信息
{redis地址}:{redis端口}>cluster nodes #查看集群节点列表

//查看集群内主从关系
{redis地址}:{redis端口}>cluster slots

//数据验证
插入数据:
{redis地址}:{redis端口}> set name
{redis地址}:{redis端口}> get name
登录其他节点查看数据:
redis-cli -a {redis密码} -h  {redis地址} -p {redsi端口} -c
{redis地址}:{redis端口}> get mykey

image

image

故障恢复

假设你现在有一个3主3从的redis cluster,很不幸运,你丢了2个节点
redis cluster集群状态为fail,丢失了一些分片

集群坏了原因分析:
* master节点能启动,但是master节点的IP变化了,集群还是根据旧的IP去连接节点,导致集群不能自愈。
* master节点某种原因不能启动,slave节点坏掉,有部分槽位slot丢失
* master节点因为网络原因不能连接,部分分片丢失,有部分槽位slot丢失


修复步骤:
//需要把dump.rdb或者appendonly.aof文件拷贝出来,目的是先恢复redis节点数据, 如果数据能恢复,可能不需要fix修复命令,集群就可能恢复
//连接任意一个集群节点,cluster forget删除掉有故障的节点。这个时候建议你用call命令,这个命令很好用   
redis-cli  --cluster call 192.168.8.101:6381   cluster  forget  <xxx_node_id>   
redis-cli  --cluster call 192.168.8.101:6381   cluster  nodes 

//meet命令添加节点 
redis-cli  --cluster call 192.168.8.101:6381   cluster meet  192.168.8.101 6384

//查询检查集群信息是否一致  
redis-cli  --cluster call 192.168.8.101:6381   cluster  nodes
redis-cli  --cluster check 192.168.8.101:6381
//如果这个时候足够幸运,cluster应该是恢复了。如果提示[ERR] Not all 16384 slots are covered by nodes.

//接下来需要fix修复命令,在这个步骤你也可以使用命令add-node节点增加集群节点
redis-cli --cluster add-node 192.168.8.102:6384 192.168.8.101:6381
//fix修复节点命令,fix修复命令,不仅可以自动删除disconnected的节点,而且会迁移没有分配的slots到正常节点,可以使集群状态fail转变为ok。我之所以手动先给集群增加一个节点,手动删除有故障节点,然后fix修复命令,fix是会迁移的slots,需要代价的,fix完成后,还需要再平衡rebalance集群。
redis-cli --cluster  fix  192.168.8.101  6381

//再平衡rebalance集群
redis-cli --cluster rebalance --cluster-use-empty-masters  --cluster-pipeline 1000 --cluster-simulate  192.168.8.101 6384
  rebalance      host:port # 指定集群的任意一节点进行平衡集群节点slot数量 

                 --cluster-weight <node1=w1...nodeN=wN> # 指定集群节点的权重

                 --cluster-use-empty-masters # 设置可以让没有分配slot的主节点参与,默认不允许

                 --cluster-timeout <arg> # 设置migrate命令的超时时间

                 --cluster-simulate # 模拟rebalance操作,不会真正执行迁移操作

                 --cluster-pipeline <arg> # 定义cluster getkeysinslot命令一次取出的key数量,默认值为10

                 --cluster-threshold <arg> # 迁移的slot阈值超过threshold,执行rebalance操作

                 --cluster-replace # 是否直接replace到目标节点
				 
				 
//最后不忘记保存配置  
cluster saveconfig

读取key的小细节

我部署了三主,没有从的集群,即replica=0
集群正常时,存了一个age:32,卡槽在741
image

kill一个主8001端口,3-5秒内仍可以连接redis集群,可以看到访问741卡槽的时候被拒绝
image

3-5秒后,集群报错connected refused,无法再使用
image

重启8001端口,集群因为没有从节点,无法自愈,需要人为修复,修复方式请参考另一篇修复cluster集群故障的文档

docker部署cluster集群

准备三台机器,一台机器也可以

提前编辑好配置文件

cd /root/redis		//这里目录可以自定义,只要后面docker run的时候改一下启动命令即可

vim redis.conf

# bind 127.0.0.1  #IP地址需要注释;
port ${PORT}	
protected-mode no	
cluster-enabled yes
cluster-config-file nodes-${PORT}.conf
cluster-node-timeout 5000
cluster-announce-ip 10.0.18.8
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
appendonly yes
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

//bind:IP地址需要注释;
//port:节点端口;
//requirepass:添加访问认证;
//masterauth:如果主节点开启了访问认证,从节点访问主节点需要认证;
//protected-mode:保护模式,默认值 yes,即开启。开启保护模式以后,需配置 bind ip 或者设置访问密码;关闭保护模式,外部网络可以直接访问;
//daemonize:是否以守护线程的方式启动(后台启动),默认 no
//appendonly:是否开启 AOF 持久化模式,默认 no;
//cluster-config-file:集群节点信息文件;
//cluster-node-timeout:集群节点连接超时时间;
//cluster-announce-ip:集群节点 IP,填写宿主机的 IP;是的,宿主机的ip,redis在哪个宿主机运行就改成那台宿主机的Ip
//cluster-announce-port:集群节点映射端口;
//cluster-announce-bus-port:集群节点总线端口。

每个 Redis 集群节点都需要打开两个 TCP 连接。
一个用于为客户端提供服务的正常 Redis TCP 端口,例如 6379。还有一个基于 6379 端口加 10000 的端口,比如 16379。
第二个端口用于集群总线,这是一个使用二进制协议的节点到节点通信通道。

节点使用集群总线进行故障检测、配置更新、故障转移授权等等。
客户端永远不要尝试与集群总线端口通信,与正常的 Redis 命令端口通信即可
但是请确保防火墙中的这两个端口都已经打开,否则 Redis 集群节点将无法通信

创建文件夹

一台机器

for port in `seq 9001 9006`; do \
  mkdir -p ./redis-cluster/${port}/conf \
  && PORT=${port} envsubst < ./redis.conf > ./redis-cluster/${port}/conf/redis.conf \
  && mkdir -p ./redis-cluster/${port}/data; \
done

三台机器

for port in `seq 9001 9002`; do \
  mkdir -p ./redis-cluster/${port}/conf \
  && PORT=${port} envsubst < ./redis.conf > ./redis-cluster/${port}/conf/redis.conf \
  && mkdir -p ./redis-cluster/${port}/data; \
done

在机器上分别启动redis

一台机器

for port in `seq 9001 9006`; do \
  docker run -itd --name redis${port}  \
  -v /root/redis/redis-cluster/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf  \
  -v /root/redis/redis-cluster/${port}/data:/data \
  -p ${port}:${port} -p 1${port}:1${port} \
  --env TZ=Asia/Shanghai --restart=always  \
  192.168.48.90:80/ecs-component/ecs-redis:6.0.9-nopersistence;done

三台机器

for port in `seq 9001 9002`; do \
  docker run -itd --name redis${port}  \
  -v /root/redis/redis-cluster/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf  \
  -v /root/redis/redis-cluster/${port}/data:/data \
  -p ${port}:${port} -p 1${port}:1${port} \
  --env TZ=Asia/Shanghai --restart=always  \
  192.168.48.90:80/ecs-component/ecs-redis:6.0.9-nopersistence;done

进入任一redis容器启动redis集群

一台机器

docker exec -it redis9001 redis-cli --cluster create 192.168.48.33:9001 192.168.48.33:9002 192.168.48.33:9003 192.168.48.33:9004 192.168.48.33:9005 192.168.48.33:9006 --cluster-replicas 1

三台机器

docker exec -it redis9001 redis-cli --cluster create 192.168.48.33:9001 192.168.48.33:9002 192.168.48.91:9001 192.168.48.91:9002  192.168.2.172:9001 192.168.2.172:9002 --cluster-replicas 1
posted @ 2022-08-24 13:20  liwenchao1995  阅读(720)  评论(0编辑  收藏  举报