前言
上一节我们讲到Redis的主从复制,顺便也提到了主从复制的缺陷,因为它将所有的写操作都是先在Master上操作,然后同步更新到Slave上,这种方式会有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。
因此本节讲到的Redis Cluster高可用高并发集群就是来替代上面这种方式,解决这一系列问题。
中心化和去中心化
在展开讲Redis集群之前我们先介绍一下集群中涉及到的两个概念,中心化和去中心化。
中心化
中心化的意思是所有的子节点都要有一个主节点并依附于它,上节讲到的主从复制的案例就是个很好的栗子。
这种方式的缺点就很明显啦,如果中心挂了,那么整个服务就都挂了,并且中心处理数据的能力有限,不能把节点性能发挥到最大。
去中心化
而去中心化的意思就是去掉中心路由,由我自己来路由,以前当Slave的时候还要看Master的脸色吧,现在我自己单干!在不需要Master分配的情况下,自己也能够独立的完成各项操作,并且搭建集群,和周围的节点建立联系,进而形成新的主机之间的通信网络。
总结以上以上上面的概念,中心化就是几个经过认证的嘉宾在讲话,所有其他人在听。就好比百家讲坛,只有一个专家在台上讲,下面的观众听就完事儿啦。
去中心化也就是每个人都可以发言,并且都可以选择听或者讲。这种方式更"民主"!
Redis集群的执行流程分析
哈希槽说明
Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个key-value时,Redis先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。
如下面这张图,当我们执行set name rose
写入操作时,Redis会使用crc16算法对name进行计算,然后将结果对16384取余数,假设我们计算完之后,余数为2500,那么这个key-value就会被分配到Redis:2
(哈希槽为5000-10000之间)。
当你往Redis Cluster中加入一个Key时,会根据crc16(key) mod 16384计算这个key应该分布到哪个hash slot中,一个hash slot中会有很多key和value。你可以理解成表的分区,使用单节点时的Redis时只有一个表,所有的key都放在这个表里。当改用Redis Cluster以后会自动为你生成16384个分区表,你insert数据时会根据上面的简单算法来决定你的key应该存在哪个分区,每个分区里可以存在多个key。
执行流程分析
假如Redis集群里面能存放90个key,那么Redis集群把90key平分到3个主机,Redis对每个主机里面30个存储位置都编号,当应用连接到主机1上面时,应该发送一个写的命令,主机使用crc16算出槽号,如果槽号在1-30 可以直接操作主机1,如果槽号在31-60那么redis会转发到主机2,如果应该再发一个命令set age 22,那么主机2使用crc16再算槽号再转发,在下面的案例中我们还会讲到。
Redis集群的搭建
接下来咱们使用去中心化的思想来搭建Redis集群,集群规则的如下,由于设施有限,只有一台主机,所以咱们就通过变更端口号的方式来区分各个主机,当然在实际开发中我们会使用多台主机联通的方式,这样处理的化,通过IP地址就可以天然的区分各个主机了。
参考文档 Redis Cluster Doc
机器编号 | ip | port |
---|---|---|
1 | 192.168.144.139 | 7000 |
2 | 192.168.144.139 | 7001 |
3 | 192.168.144.139 | 7002 |
4 | 192.168.144.139 | 7003 |
5 | 192.168.144.139 | 7004 |
6 | 192.168.144.139 | 7005 |
集群搭建过程
第一步:新建文件夹
切换到/usr/local
路径下新建redis-cluster
文件夹
第二步:准备一个服务端程序
将redis-server
移到当前路径下,方便使用
[root@localhost local]# cp redis/bin/redis-server redis-cluster/
[root@localhost local]# ls redis-cluster/
redis-server
第三步:创建六个文件夹
以下这六个文件夹是用来存储6个不同的redis.conf
配置文件的。
[root@localhost local]# cd redis-cluster/
[root@localhost redis-cluster]# mkdir redis-1
[root@localhost redis-cluster]# mkdir redis-2
[root@localhost redis-cluster]# mkdir redis-3
[root@localhost redis-cluster]# mkdir redis-4
[root@localhost redis-cluster]# mkdir redis-5
[root@localhost redis-cluster]# mkdir redis-6
第四步:准备6个redis.conf配置文件
首先我们将之前已经存在的redis.conf
文件分别拷贝六份依次放到到之前创建的文件夹中
[root@localhost redis-cluster]# cp /root/myredis/redis.conf /usr/local/redis-cluster/redis-1
[root@localhost redis-cluster]# cp /root/myredis/redis.conf /usr/local/redis-cluster/redis-2
[root@localhost redis-cluster]# cp /root/myredis/redis.conf /usr/local/redis-cluster/redis-3
[root@localhost redis-cluster]# cp /root/myredis/redis.conf /usr/local/redis-cluster/redis-4
[root@localhost redis-cluster]# cp /root/myredis/redis.conf /usr/local/redis-cluster/redis-5
[root@localhost redis-cluster]# cp /root/myredis/redis.conf /usr/local/redis-cluster/redis-6
紧接着按照以下方式,配置咱们的redis.conf
,需要修改的内容在下面均有体现
#进入各个配置文件中,按照以下配置信息依次进行修改
[root@localhost redis-cluster]# vim redis-2/redis.conf
[root@localhost redis-cluster]# vim redis-3/redis.conf
[root@localhost redis-cluster]# vim redis-4/redis.conf
[root@localhost redis-cluster]# vim redis-5/redis.conf
[root@localhost redis-cluster]# vim redis-5/redis.conf
[root@localhost redis-cluster]# vim redis-6/redis.conf
##########################################################
Redis-1
bind 0.0.0.0 69行
port 7000 92行
daemonize yes 136行
# 打开aof 持久化
appendonly yes 672行
# 开启集群
cluster-enabled yes 814行
# 集群的配置文件,该文件自动生成
cluster-config-file nodes-7000.conf 822行
# 集群的超时时间
cluster-node-timeout 5000 828行
------------------------------------
Redis-2
daemonize yes
bind 0.0.0.0
port 7001
# 打开aof 持久化
appendonly yes
# 开启集群
cluster-enabled yes
# 集群的配置文件,该文件自动生成
cluster-config-file nodes-7001.conf
# 集群的超时时间
cluster-node-timeout 5000
-------------------------------------
Redis-3
daemonize yes
bind 0.0.0.0
port 7002
# 打开aof 持久化
appendonly yes
# 开启集群
cluster-enabled yes
# 集群的配置文件,该文件自动生成
cluster-config-file nodes-7002.conf
# 集群的超时时间
cluster-node-timeout 5000
------------------------------------
Redis-4
daemonize yes
bind 0.0.0.0
port 7003
# 打开aof 持久化
appendonly yes
# 开启集群
cluster-enabled yes
# 集群的配置文件,该文件自动生成
cluster-config-file nodes-7004.conf
# 集群的超时时间
cluster-node-timeout 5000
-------------------------------------
Redis-5
daemonize yes
bind 0.0.0.0
port 7004
# 打开aof 持久化
appendonly yes
# 开启集群
cluster-enabled yes
# 集群的配置文件,该文件自动生成
cluster-config-file nodes-7005.conf
# 集群的超时时间
cluster-node-timeout 5000
--------------------------------------
Redis-6
daemonize yes
bind 0.0.0.0
port 7005
# 打开aof 持久化
appendonly yes
# 开启集群
cluster-enabled yes
# 集群的配置文件,该文件自动生成
cluster-config-file nodes-7006.conf
# 集群的超时时间
cluster-node-timeout 5000
第五步:同时启动所有的redis
使用./redis-server
启动所有的配置文件,运行这个六个Redis
执行完毕之后,可以使用ps -ef|grep redis
指令查看Redis是否都启动成功了。
第六步:使用Docker下载redis-trib的镜像运行
#安装Docker
yum install docker
#启动Docker
systemctl start docker
#下载镜像
docker pull inem0o/redis-trib
下载完成之后调用docker run -it --net host inem0o/redis-trib create --replicas 1
指令运行redis-trib
镜像
这里的-it
是为了进行交互,输入内容,--net host
是为了让docker容器能连接上本地的宿主机。
docker run -it --net host inem0o/redis-trib create --replicas 1
192.168.144.139:7000 192.168.144.139:7001
192.168.144.139:7002 192.168.144.139:7003
192.168.144.139:7004 192.168.144.139:7005
运行成功后的界面如下
第九步:测试集群环境
将redis-cli
的指令也拷贝过来
注意,以下命令开启reids命令中的-c
(cluster)表示连接集群
[root@localhost redis-cluster]# ./redis-cli -c -h 192.168.144.139 -p 7000
192.168.144.139:7001> lpush list 1 2 3 4
-> Redirected to slot [12291] located at 192.168.144.139:7002
(integer) 4
192.168.144.139:7002> set name marco
-> Redirected to slot [5798] located at 192.168.144.139:7001
OK
大家注意看Redirected to slot [12291] located at 192.168.144.139:7002
,这条数据中的slot[12291]
就是我们上面提到的哈希槽,正常情况下,当我们第一次进入Redis中并执行写的命令时,是由第一台机器使用crs
计算key在哪个卡槽(就是我们启动栏里的第一台 192.168.144.139:7000 机器),上面的指令执行完成之后就会跳到卡槽为slot[12291]
的机器上,从下面的Redirected to slot [5798] located at 192.168.144.139:7001
可以看出slot[12291]
卡槽是被分配在IP为192.168.144.139:7002的主机上的。