Redis集群
Redis Cluster概述
- redis是一个开源的key value存储系统,受到了广大互联网公司的青睐。redis3.0版本之前只支持单例模式,在3.0版本及以后才支持集群。
- redis集群采用P2P模式,是完全去中心化的,不存在中心节点或者代理节点。即Redis集群原理就是去中心化。
- redis集群是没有统一的入口的,客户端(client)连接集群的时候连接集群中的任意节点(node)即可,集群内部的节点是相互通信的(PING-PONG机制),每个节点都是一个redis实例;
- 为了实现集群的高可用,即判断节点是否健康(能否正常使用),redis-cluster有这么一个投票容错机制:如果集群中超过半数的节点投票认为某个节点挂了,那么这个节点就挂了(fail)。这是判断节点是否挂了的方法;
- 判断集群是否挂了:如果集群中任意一个节点挂了,而且该节点没有从节点(备份节点),那么这个集群就挂了。
- 为什么任意一个节点挂了(没有从节点)这个集群就挂了呢?
- 因为集群内置了16384个slot(哈希槽),并且把所有的物理节点映射到了这16384[0-16383]个slot上,或者说把这些slot均等的分配给了各个节点。当需要在Redis集群存放一个数据(key-value)时,redis会先对这个key进行crc16算法,然后得到一个结果。再把这个结果对16384进行求余,这个余数会对应[0-16383]其中一个槽,进而决定key-value存储到哪个节点中。所以一旦某个节点挂了,该节点对应的slot就无法使用,那么就会导致集群无法正常工作。
- 综上所述,每个Redis集群理论上最多可以有16384个节点。
中心化和去中心化
中心化
意思是所有的节点都要有一个主节点。
缺点:中心挂了,服务就挂了。中心处理数据的能力有限,不能把节点性能发挥到最大。
特点:就是一个路由作用
去中心化
概念:在一个分布有众多节点的系统中,每个节点都具有高度自治的特征。节点之间彼此可以自由连接,形成新的连接单元。任何一个节点都可能成为阶段性的中心,但不具备强制性的中心控制功能。节点与节点之间的影响,会通过网络而形成非线性因果关系。这种开放式、扁平化、平等性的系统现象或结构,我们称之为去中心化。
特点:去掉路由,我自己来路由。每个节点都可以当做中心。
哈希槽
Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。
当你往Redis Cluster中加入一个Key时,会根据crc16(key) mod 16384
计算这个key应该分布到哪个hash slot中,一个hash slot中会有很多key和value。你可以理解成表的分区,使用单节点时的redis时只有一个表,所有的key都放在这个表里;改用Redis Cluster以后会自动为你生成16384个分区表,你insert数据时会根据上面的简单算法来决定你的key应该存在哪个分区,每个分区里有很多key。
执行流程分析
1、假如redis集群里面能存放90个key,那么redis集群把90key平分到3个主机。
2、redis对每个主机里面30个存储位置都编号,当应用连接到主机1上面时,应该发送一个写的命令。
3、主机使用crc16算出槽号。
4、如果槽号在1-30 可以直接操作主机1,如果槽号在31-60那么redis会转发到主机2。
5、如果应该再发一个命令如set age 22
,那么主机2使用crc16再算槽号再转发。
Redis集群搭建
中文文档教程:http://redis.cn/topics/cluster-tutorial.html
需要的环境
Redis集群至少需要3个节点,因为投票容错机制要求超过半数节点认为某个节点挂了该节点才是挂了,所以2个节点无法构成集群。
要保证集群的高可用,需要每个节点都有从节点,也就是备份节点,所以Redis集群至少需要6台服务器。因为我没有那么多服务器,也启动不了那么多虚拟机,所在这里搭建的是伪分布式集群,即一台服务器虚拟运行6个redis实例,修改端口号为(7001-7006),当然实际生产环境的Redis集群搭建和这里是一样的。
安装ruby。如果使用Docker安装则不需要。
集群规则
搭建过程
本文使用的Redis5.x版本。使用Docker搭建。
下面是一个最少选项的集群的配置文件:
port 7000 #端口
cluster-enabled yes #开启集群
cluster-config-file nodes.conf #集群的配置文件,该文件自动生成
cluster-node-timeout 5000 #集群的超时时间
appendonly yes #打开aof持久化
文件中的 cluster-enabled
选项用于开实例的集群模式, 而 cluster-conf-file
选项则设定了保存节点配置文件的路径, 默认值为 nodes.conf
节点配置文件无须人为修改, 它由 Redis 集群在启动时创建, 并在有需要时自动进行更新。
要让集群正常运作至少需要三个主节点,不过在刚开始试用集群功能时, 强烈建议使用六个节点: 其中三个为主节点, 而其余三个则是各个主节点的从节点。
准备6个redis服务器
1、创建目录存放redis集群
[root@localhost ~]# mkdir redis-cluster
[root@localhost ~]# cd redis-cluster/
2、将/usr/local/redis下的service和客户端指令copy一份,方便操作
[root@localhost redis-cluster]# cp /usr/local/redis/bin/redis-cli ./
[root@localhost redis-cluster]# cp /usr/local/redis/bin/redis-server ./
3、创建6个目录存放集群
[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
4、copy配置文件并配置,6份配置除了端口一样
[root@localhost redis-cluster]# cp /usr/local/src/redis/redis.conf ./redis-1/
[root@localhost redis-cluster]# vim redis-1/redis.conf
5、修改
:set nu #显示行号
69行 bind 127.0.0.1 改为 bind 0.0.0.0
92行 port 6379 改为 port 7001
136行 daemonize yes
158 pidfile /var/run/redis_6379.pid 修改端口为7001
699行 appendonly no 改为 appendonly yes
838 打开 cluster-enabled yes
846 打开 cluster-config-file nodes-6379.conf 修改端口为7001
852 打开 cluster-node-timeout 15000
6、将配置好的redis1配置copy5份,并进行修改(替换端口号)
[root@localhost redis-cluster]# cp redis-1/redis.conf ./redis-2/
[root@localhost redis-cluster]# cp redis-1/redis.conf ./redis-3/
[root@localhost redis-cluster]# cp redis-1/redis.conf ./redis-4/
[root@localhost redis-cluster]# cp redis-1/redis.conf ./redis-5/
[root@localhost redis-cluster]# cp redis-1/redis.conf ./redis-6/
[root@localhost redis-cluster]# vim redis-1/redis.conf
:%s/7001/7002/g #全文替换7001为7002 (会显示3次替换,共3行)
7、启动这6个服务
[root@localhost redis-cluster]# ./redis-server ./redis-1/redis.conf
[root@localhost redis-cluster]# ./redis-server ./redis-2/redis.conf
[root@localhost redis-cluster]# ./redis-server ./redis-3/redis.conf
[root@localhost redis-cluster]# ./redis-server ./redis-4/redis.conf
[root@localhost redis-cluster]# ./redis-server ./redis-5/redis.conf
[root@localhost redis-cluster]# ./redis-server ./redis-6/redis.conf
8、查看进程
[root@localhost redis-cluster]# ps -ef|grep redis
9、可以测试连接其中一个
[root@localhost redis-cluster]# ./redis-cli -p 7001
127.0.0.1:7001> ping
PONG
127.0.0.1:7001> set name zhangsan
(error) CLUSTERDOWN Hash slot not served #显示未提供hash槽
我们现在只是开启了6个redis的实例,还没有配置集群。
使用docker配置redis集群
[root@localhost redis-cluster]# docker pull inem0o/redis-trib
#-it是为了可以输入
#--net host 是为了上docker容器能连接上本地的宿主机
docker run -it --net host inem0o/redis-trib create --replicas 1 192.168.81.130:7001 192.168.81.130:7002 192.168.81.130:7003 192.168.81.130:7004 192.168.81.130:7005 192.168.81.130:7006
Redi集群搭建成功。最后一段文字,显示了每个节点所分配的slots(哈希槽),这里总共6个节点,其中3个是从节点,所以3个主节点分别映射了0-5460、5461-10922、10933-16383solts。
连接集群并测试
# -c 表示连接集群
[root@localhost redis-cluster]# ./redis-cli -c -p 7001
#查看当前集群信息
cluster info
#查看集群里有多少个节点
cluster nodes