Redis Cluster
单台机器故障,在生产环境中是发生概率较高的事情,如果因为某台机器故障而影响了整个系统,那只能说明这个系统非常的不健壮。如果是采用分布式的部署方案,就可以尽量地避免单点问题。
今天来简单介绍下,Redis的官方多机部署方案,Redis Cluster。 一组Redis Cluster是由多个Redis实例组成,官方推荐我们使用6实例,其中3个为主节点,3个为从结点。一旦有主节点发生故障的时候,Redis Cluster可以选举出对应的从结点成为新的主节点,继续对外服务,从而保证服务的高可用性。
Cluster是 Redis 官方在 3.0 版本推出的一套分布式存储方案,其结构如下
Cluster 主要具备以下两个功能:
数据分区
Redis 集群会将用户数据分散保存至各个节点中,突破单机 Redis 内存最大存储容量。集群引入了 哈希槽slot的概念,其搭建完成后会生 16384 个哈希槽slot,同时会根据节点的数量大致均等的将 16384 个哈希槽映射到不同的节点上。当用户存储key-value时,集群会先对key进行 CRC16 校验然后对 16384 取模来决定key-value放置哪个槽,从而实现自动分割数据到不同的节点上。
数据冗余
Redis 集群支持主从复制和故障恢复。集群使用了主从复制模型,每个主节点master应至少有一个从节点slave。假设某个主节点故障,其所有子节点会广播一个数据包给集群里的其他主节点来请求选票,一旦某个从节点收到了大多数主节点的回应,那么它就赢得了选举,被推选为主节点,负责处理之前旧的主节点负责的哈希槽。
关于 Redis Cluster 详细介绍以及实现原理请参见 Redis Cluster 教程 和 Redis Cluster 规范,在此不再赘述。
下面我们开始搭建 cluster
首先,需要大家在linux中已经安装了redis,如果没有没有安装的,可以参见 redis编译安装
安装完成后,笔者先说自己的环境:
- 首先笔者有三台服务器(阿里云服务器、阿里云轻量级服务器、腾讯云服务器)。
- cluster集群,最少需要三主三从(最低要求),意味着笔者必须在某台服务器中多开redis。
- 如果你只有一台服务器,则需要在一台服务器开启6个redis
介绍完笔者的环境,笔者规划在其中一台服务器中,开启四个redis,通过如下命令创建各个节点启动配置文件的存放目录
mkdir /usr/local/redis-cluster
cd redis-cluster
mkdir 8001 8002 8003
顺序执行下面的命令,进入 Redis 源码包目录并将默认配置文件redis.conf分别复制到三个节点配置存放目录中,作为各自节点启动配置文件。
cd /usr/local/redis/etc
cp redis.conf /usr/local/redis-cluster/8001
cp redis.conf /usr/local/redis-cluster/8002
cp redis.conf /usr/local/redis-cluster/8003
接下来,需要修改复制过来的三个节点配置,修改以下的配置,下方是笔者的/usr/local/redis-cluster/8001/redis.conf 配置,别忘记把其他服务器的redis配置,也根据下方的配置进行修改
port 7001 # 运行端口
pidfile /var/run/redis_8001.pid # 设置 Redis 实例 pid 文件
daemonize yes # 以守护进程运行 Redis 实例
cluster-enabled yes # 启用集群模式
cluster-node-timeout 15000 # 设置当前节点连接超时毫秒数
cluster-config-file nodes-8001.conf # 设置当前节点集群配置文件路径
修改完成后,开始启动这三个redis
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/8001/redis.conf
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/8002/redis.conf
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/8003/redis.conf
查看是否启动成功
ps -aux|grep redis
到了这里,如果安装的 Redis 是 3.x 和 4.x 的版本可以使用 redis-trib.rb 搭建,不过之前需要安装 Ruby 环境。
先使用 yum 安装 Ruby 环境以及其他依赖项。
yum -y install ruby ruby-devel rubygems rpm-build
检查是否安装完成以及查看版本
[root@iZwz96c7qipsxts04f37u4Z local]# ruby -v
ruby 2.0.0p648 (2015-12-16) [x86_64-linux]
在这里,如果你是 3.x 和 4.x版本的redis,需要使用redis-trib.rb搭建,而 笔者的redis版本是6.0^,所以笔者使用的是 redis-cli --cluster create
/usr/bin/redis-cli --cluster create 主服务器ip地址:端口号 主服务器ip地址:端口号 主服务器ip地址:端口号 从服务器ip地址:端口号 从服务器ip地址:端口号 从服务器ip地址:端口号 --cluster-replicas 1
主节点在前,从节点在后。其中 –cluster-replicas 参数用来指定一个主节点带有的从节点个数,如上 –cluster-replicas 1即表示 1 个主节点有 1 个从节点。
这时候,如果 Waiting for the cluster to join… 一直在等待的话,则不需要在等待了,直接Ctrl+c结束掉,因为放行端口没有开放。
- Redis Cluster节点之间会定期交换Gossip消息,以及做一些心跳检测Redis,通过ping/pong消息实现故障发现。
- 所以需要每台服务器,都需要将redis的端口放行。
- 比如笔者 上方有一台服务器是启动了四个redis 分别是 6379 8001 8002 8003。
- 则笔者需要在每台服务器都放行这些端口,云服务器需要开启安全组,轻量级服务器需要手动放行端口。
- 单单放行了redis端口还不够,还需要放行集成端口,如果笔者redis 为6379 则需要放行16379,redis 为8001则需要放行18001,以此类推。
还有可能会出现以下故障 Node 服务器Ip地址:端口号 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0
- 把cluster-config-file生成的配置文件删除。
- 将需要新增的节点下aof、rdb等本地备份文件删除;pid文件删除;如果还不行就登录进去 flushall。
- kill掉所有的Redis服务,重新启动。
完成后,我们尝试往redis中的master节点写入一个数据
set hello helloword
上面是笔者的可视化工具界面,可以看到,当一个master节点写入了数据,会根据哈希槽来确定数据存放的主节点,而从节点会将主节点的数据复制一份
总结:
主从复制
复制的作用是把redis的数据库复制多个副本部署在不同的服务器上,如果其中一台服务器出现故障,也能快速迁移到其他服务器上提供服务。 复制功能可以实现当一台redis服务器的数据更新后,自动将新的数据同步到其他服务器上
主从复制就是我们常见的master/slave模式, 主数据库可以进行读写操作,当写操作导致数据发生变化时会自动将数据同步给从数据库。而一般情况下,从数据库是只读的,并接收主数据库同步过来的数据。 一个主数据库可以有多个从数据库
上面那个例子里, 集群有ABC三个主节点, 如果这3个节点都没有加入从节点,如果B挂掉了,我们就无法访问整个集群了。A和C的slot也无法访问。
注:
我们在集群建立的时候,一定要为每个主节点都添加了从节点, 比如像这样, 集群包含主节点A、B、C, 以及从节点A1、B1、C1, 那么即使B挂掉系统也可以继续正确工作。
B1节点替代了B节点,所以Redis集群将会选择B1节点作为新的主节点,集群将会继续正确地提供服务。 当B重新开启后,它就会变成B1的从节点。
不过需要注意,如果节点B和B1同时挂了,Redis集群就无法继续正确地提供服务了。