1、在 linux 下执行命令:
mkdir -p /etc/redis-cluster
mkdir -p /var/log/redis
mkdir -p /var/redis/7001
mkdir -p /var/redis/7002
mkdir -p /var/redis/7003
mkdir -p /var/redis/7004
mkdir -p /var/redis/7005
mkdir -p /var/redis/70062、添加 redis cluster 配置:
port 7001
cluster-enabled yes
cluster-config-file /etc/redis-cluster/node-7001.conf
cluster-node-timeout 15000
daemonize yes
pidfile /var/run/redis_7001.pid
dir /var/redis/7001
logfile /var/log/redis/7001.log
bind 192.168.31.136
appendonly yes
port 7002
cluster-enabled yes
cluster-config-file /etc/redis-cluster/node-7002.conf
cluster-node-timeout 15000
daemonize yes
pidfile /var/run/redis_7002.pid
dir /var/redis/7002
logfile /var/log/redis/7002.log
bind 192.168.31.136
appendonly yes
port 7003
cluster-enabled yes
cluster-config-file /etc/redis-cluster/node-7003.conf
cluster-node-timeout 15000
daemonize yes
pidfile /var/run/redis_7003.pid
dir /var/redis/7003
logfile /var/log/redis/7003.log
bind 192.168.31.139
appendonly yes
port 7004
cluster-enabled yes
cluster-config-file /etc/redis-cluster/node-7004.conf
cluster-node-timeout 15000
daemonize yes
pidfile /var/run/redis_7004.pid
dir /var/redis/7004
logfile /var/log/redis/7004.log
bind 192.168.31.139
appendonly yes
port 7005
cluster-enabled yes
cluster-config-file /etc/redis-cluster/node-7005.conf
cluster-node-timeout 15000
daemonize yes
pidfile /var/run/redis_7005.pid
dir /var/redis/7005
logfile /var/log/redis/7005.log
bind 192.168.31.138
appendonly yes
port 7006
cluster-enabled yes
cluster-config-file /etc/redis-cluster/node-7006.conf
cluster-node-timeout 15000
daemonize yes
pidfile /var/run/redis_7006.pid
dir /var/redis/7006
logfile /var/log/redis/7006.log
bind 192.168.31.138
appendonly yes3、安装 ruby
yum install -y ruby
yum install -y rubygems
gem install redis
#ruby版本过低
cd /home/legou/ruby
wget https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.3.tar.gz
tar zxvf ruby-2.5.3.tar.gz
cd ruby-2.5.3
./configure --prefix=/usr/local/ruby
make && make install
/usr/local/ruby/bin/ruby -v #查看安装后的版本
echo "export PATH=$PATH:/usr/local/ruby/bin" >> /etc/profile
source /etc/profile
echo $PATH # 验证
gem install redis4、将 redis 的配置文件,分别在三台机器的/etc/redis下放置,分别为: node-7001.conf,node-7002.conf,node-7003.conf,node-7004.conf,node-7005.conf,node-7006.conf
5、在/etc/init.d下,放启动脚本,分别为: redis_7001, redis_7002, redis_7003, redis_7004, redis_7005, redis_7006,(每个启动脚本内,都修改对应的端口号)
6、分别在3台机器上,启动6个 redis 实例
./redis_7001 start7、启动 redis cluster
cp /usr/local/redis-3.2.8/src/redis-trib.rb /usr/local/bin
redis-trib.rb create --replicas 1 192.168.31.187:7001 192.168.31.187:7002 192.168.31.19:7003 192.168.31.19:7004 192.168.31.227:7005 192.168.31.227:7006
redis-trib.rb check 192.168.31.187:70018、redis cluster 的扩容和删除
1)添加 node 作为 master
mkdir -p /var/redis/7007
# node config
port 7007
cluster-enabled yes
cluster-config-file /etc/redis-cluster/node-7007.conf
cluster-node-timeout 15000
daemonize yes
pidfile /var/run/redis_7007.pid
dir /var/redis/7007
logfile /var/log/redis/7007.log
bind 192.168.31.227
appendonly yes拷贝一个 redis_7007 启动脚本,然后执行
#启动node
./redis_7001 start
#在 redis cluster 添加节点
redis-trib.rb add-node 192.168.31.227:7007 192.168.31.187:7001
#检查7001的slave节点信息
redis-trib.rb check 192.168.31.187:7001
# 把一部分 hash slot 从一些 node 上迁移到另外一些 node 上
redis-trib.rb reshard 192.168.31.187:70012)添加 node 作为slave
mkdir -p /var/redis/7008
port 7008
cluster-enabled yes
cluster-config-file /etc/redis-cluster/node-7008.conf
cluster-node-timeout 15000
daemonize yes
pidfile /var/run/redis_7008.pid
dir /var/redis/7008
logfile /var/log/redis/7008.log
bind 192.168.31.227
appendonly yes
redis-trib.rb add-node --slave --master-id 28927912ea0d59f6b790a50cf606602a5ee48108 192.168.31.227:7008 192.168.31.187:70013)删除 node,然后把 slot 均分给其它 master (master id)
redis-trib.rb reshard 192.168.31.187:7001
redis-trib.rb del-node 192.168.31.187:7001 bd5a40a6ddccbd46a0f4a2208eb25d2453c2a8db先用 resharding 将数据都移除到其他节点,确保 node 为空之后,才能执行 remove 操作
4)slave的自动迁移:master 的 salve 冗余可以实现更高的可用性。如果某个 master 挂了,redis cluster 会把该 master 的 slave 挂在其它 master 下。如果某个 master 的 slave 挂了,redis cluster 会自动迁移一个冗余的 slave 给那个 master。
redis cluster 读写分离的限制性:
redis cluster 读写分离有一定的限制性,redis cluster 的核心理念主要是用 slave 做高可用的,每个 master 挂一两个 slave,主要是做数据的热备,还有 master 故障时的主备切换,实现高可用的,redis cluster默 认是不支持 slave 节点读或者写的,跟我们手动基于 replication 搭建的主从架构不一样的。如果要在 slave 读取数据,可以先执行 readonly 指令,然后执行 get mykey1。或者用 redis-cli <ip> <port> -c 会自动进行各种底层的重定向的操作。
基础通信原理:
1)redis cluster节点间采取gossip协议进行通信
- 集中式:好处在于,元数据的更新和读取,时效性非常好,一旦元数据出现了变更,立即就更新到集中式的存储中,其他节点读取的时候立即就可以感知到。不好在于,所有的元数据的跟新压力全部集中在一个地方,可能会导致元数据的存储有压力,eg:zookeper 实现。
- gossip:好处在于元数据的更新比较分散,不是集中在一个地方,更新请求会陆陆续续,打到所有节点上去更新,有一定的延时,降低了压力。缺点,元数据更新有延时,可能导致集群的一些操作会有一些滞后
2)10000端口:每个节点有一个专门用于节点间通信端口,服务的端口号+10000,比如7001,那么用于节点间通信的就是17001
3)gossip协议:ping,pong,meet,fail 等
- meet: 某个节点发送 meet 给新加入的节点,让新节点加入集群中,然后新节点就会开始与其他节点进行通信
- ping: 每个节点都会频繁给其他节点发送ping,其中包含自己的状态还有自己维护的集群元数据,互相通过ping交换元数据
- pong: 返回 ping 和 meet,包含自己的状态和其他信息,也可以用于信息广播和更新
- fail: 某个节点判断另一个节点 fail 之后,就发送 fail 给其他节点,通知其他节点,指定的节点宕机了
高可用性与主备切换原理:和哨兵是类似的
1、判断节点宕机:如果一个节点认为另外一个节点宕机,那么就是 pfail,主观宕机,如果多个节点都认为另外一个节点宕机了,那么就是 fail,在 cluster-node-timeout 内,某个节点一直没有返回 pong,那么就被认为 pfail。如果一个节点认为某个节点 pfail 了,那么会在 gossip ping 消息中,ping 给其他节点,如果超过半数的节点都认为 pfail了 ,那么就会变成 fail。
2、从节点过滤:对宕机的 master node,从其所有的 slave node中选择一个切换成 master node,检查每个 slave node 与 master node 断开连接的时间,如果超过了 cluster-node-timeout * cluster-slave-validity-factor,那么就没有资格切换成 master。
3、从节点选举
- 哨兵:对所有从节点进行排序,slave priority,offset,run id
- 所有的 master node 开始 slave 选举投票,给要进行选举的slave进行投票,如果大部分 master node(N/2 + 1) 都投票给了某个从节点, 那么选举通过,那个从节点可以切换成 master,从节点执行主备切换,从节点切换为主节点。
redis 常见问题
1、fork耗时导致高并发请求延时:RDB 和 AOF 的时候,其实会有生成 RDB 快照,AOF rewrite,耗费磁盘IO的过程,主进程 fork 子进程是需要拷贝父进程的空间内存页表的,也是会耗费一定的时间的。优化思路:fork耗时跟redis主进程的内存有关系,一般控制 redis 的内存在 10B以内,slave -> master,全量复制
2、AOF 的阻塞问题:redis 将数据写入 AOF 缓冲区,单独开一个现场做 fsync 操作,每秒一次。但是 redis 主线程会检查两次 fsync 的时间,如果距离上次 fsync 时间超过了2秒,那么写请求就会阻塞。优化思路:优化硬盘写入速度,建议采用SSD,不要用普通的机械硬盘,SSD,大幅度提升磁盘读写的速度。
3、主从复制风暴问题:如果一下子让多个 slave 从 master 去执行全量复制,一份大的rdb同时发送到多个 slave,会导致网络带宽被严重占用。优化思路:如果一个master真的要挂载多个slave,那尽量用树状结构。
4、vm.overcommit_memory 如果是0的话,可能导致类似fork等操作执行失败,申请不到足够的内存空间
- 0: 检查有没有足够内存,没有的话申请内存失败
- 1: 允许使用内存直到用完为止
- 2: 内存地址空间不能超过swap + 50%
cat /proc/sys/vm/overcommit_memory
echo "vm.overcommit_memory=1" >> /etc/sysctl.conf
sysctl vm.overcommit_memory=16、swapiness:cat /proc/version查看linux内核版本
- 如果 linux 内核版本<3.5,那么 swapiness 设置为0,这样系统宁愿 swap 也不会 oom killer(杀掉进程)
- 如果 linux 内核版本>=3.5,那么 swapiness 设置为1,这样系统宁愿 swap也不会 oom killer
保证redis不会被杀掉
echo 0 > /proc/sys/vm/swappiness
echo vm.swapiness=0 >> /etc/sysctl.conf7、最大打开文件句柄
ulimit -n 10032 100328、tcp backlog
cat /proc/sys/net/core/somaxconn
echo 511 > /proc/sys/net/core/somaxconn
















