redis主从与集群
redis主从与集群
redis(Master-Replicaset) *****
11.1 原理 (背)
1. 副本库通过slaveof 10.0.0.51 6379命令,连接主库,并发送SYNC给主库
2. 主库收到SYNC,会立即触发BGSAVE,后台保存RDB,发送给副本库
3. 副本库接收后会应用RDB快照
4. 主库会陆续将中间产生的新的操作,保存并发送给副本库
5. 到此,我们主复制集就正常工作了
6. 再此以后,主库只要发生新的操作,都会以命令传播的形式自动发送给副本库.
7. 所有复制相关信息,从info信息中都可以查到.即使重启任何节点,他的主从关系依然都在.
8. 如果发生主从关系断开时,从库数据没有任何损坏,在下次重连之后,从库发送PSYNC给主库
9. 主库只会将从库缺失部分的数据同步给从库应用,达到快速恢复主从的目的
11.2主从数据一致性保证
min-slaves-to-write 1 min-slaves-max-lag 3
11.3 主库是否要开启持久化?
如果不开有可能,主库重启操作,造成所有主从数据丢失!
12. 主从复制实现
1、环境:
准备两个或两个以上redis实例
mkdir /data/638{0..2}
配置文件示例:
cat >> /data/6380/redis.conf <<EOF port 6380 daemonize yes pidfile /data/6380/redis.pid loglevel notice logfile "/data/6380/redis.log" dbfilename dump.rdb dir /data/6380 requirepass 123 masterauth 123 EOF
cat >> /data/6381/redis.conf <<EOF
port 6381
daemonize yes
pidfile /data/6381/redis.pid
loglevel notice
logfile "/data/6381/redis.log"
dbfilename dump.rdb
dir /data/6381
requirepass 123
masterauth 123
EOF
cat >> /data/6382/redis.conf <<EOF
port 6382
daemonize yes
pidfile /data/6382/redis.pid
loglevel notice
logfile "/data/6382/redis.log"
dbfilename dump.rdb
dir /data/6382
requirepass 123
masterauth 123
EOF
启动:
redis-server /data/6380/redis.conf redis-server /data/6381/redis.conf redis-server /data/6382/redis.conf
主节点:6380
从节点:6381、6382
2、开启主从:
6381/6382命令行:
redis-cli -p 6381 -a 123 SLAVEOF 127.0.0.1 6380 redis-cli -p 6382 -a 123 SLAVEOF 127.0.0.1 6380
解除:
redis-cli -p 6381 -a 123 SLAVEOF no one
3、查询主从状态
redis-cli -p 6380 -a 123 info replication redis-cli -p 6381 -a 123 info replication redis-cli -p 6382 -a 123 info replication
哨兵(sentinel搭建过程)
mkdir /data/26380 cd /data/26380 vim sentinel.conf port 26380 dir "/data/26380" sentinel monitor mymaster 127.0.0.1 6380 1 sentinel down-after-milliseconds mymaster 5000 sentinel auth-pass mymaster 123
启动:
redis-sentinel /data/26380/sentinel.conf &>/tmp/sentinel.log &
==============================
如果有问题:
1、重新准备1主2从环境
2、kill掉sentinel进程
3、删除sentinel目录下的所有文件
4、重新搭建sentinel
================================
停主库测试:
redis-cli -p 6380 shutdown redis-cli -p 6381 info replication
启动源主库(6380),看状态。
Sentinel管理命令:
redis-cli -p 26380
PING :返回 PONG 。
SENTINEL masters :列出所有被监视的主服务器
SENTINEL slaves <master name>
SENTINEL get-master-addr-by-name <master name> : 返回给定名字的主服务器的 IP 地址和端口号。
SENTINEL reset <pattern> : 重置所有名字和给定模式 pattern 相匹配的主服务器。
SENTINEL failover <master name> : 当主服务器失效时, 在不询问其他 Sentinel 意见的情况下, 强制开始一次自动故障迁移。
14. redis cluster(集群)
14.1 介绍
高性能
1、在多分片节点中,将16384个槽位,均匀分布到多个分片节点中
2、存数据时,将key做crc16(key),然后和16384进行取模,得出槽位值(0-16383之间)
3、根据计算得出的槽位值,找到相对应的分片节点的主节点,存储到相应槽位上
4、如果客户端当时连接的节点不是将来要存储的分片节点,分片集群会将客户端连接切换至真正 存储节点进行数据存储
高可用:
在搭建集群时,会为每一个分片的主节点,对应一个从节点,实现slaveof的功能,同时当主节点 down,实现类似于sentinel的自动failover的功能。
1、redis会有多组分片构成(3组)
2、redis cluster 使用固定个数的slot存储数据(一共16384slot)
3、每组分片分得1/3 slot个数(0-5500 5501-11000 11001-16383)
4、基于CRC16(key) % 16384 ====》值 (槽位号)。
14.2 规划、搭建过程:
6个redis实例,一般会放到3台硬件服务器
注:在企业规划中,一个分片的两个分到不同的物理机,防止硬件主机宕机造成的整个分片数据丢失。
端口号:7000-7005
安装集群插件:
EPEL源安装ruby支持
yum install ruby rubygems -y
使用国内源
gem sources -l
gem sources -a http://mirrors.aliyun.com/rubygems/
gem sources --remove https://rubygems.org/
gem sources -l
gem install redis -v 3.3.3
集群节点准备
mkdir /data/700{0..5}
cat > /data/7000/redis.conf <<EOF port 7000 daemonize yes pidfile /data/7000/redis.pid loglevel notice logfile "/data/7000/redis.log" dbfilename dump.rdb dir /data/7000 protected-mode no cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes EOF cat >> /data/7001/redis.conf <<EOF port 7001 daemonize yes pidfile /data/7001/redis.pid loglevel notice logfile "/data/7001/redis.log" dbfilename dump.rdb dir /data/7001 protected-mode no cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes EOF cat >> /data/7002/redis.conf <<EOF port 7002 daemonize yes pidfile /data/7002/redis.pid loglevel notice logfile "/data/7002/redis.log" dbfilename dump.rdb dir /data/7002 protected-mode no cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes EOF cat >> /data/7003/redis.conf <<EOF port 7003 daemonize yes pidfile /data/7003/redis.pid loglevel notice logfile "/data/7003/redis.log" dbfilename dump.rdb dir /data/7003 protected-mode no cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes EOF cat >> /data/7004/redis.conf <<EOF port 7004 daemonize yes pidfile /data/7004/redis.pid loglevel notice logfile "/data/7004/redis.log" dbfilename dump.rdb dir /data/7004 protected-mode no cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes EOF cat >> /data/7005/redis.conf <<EOF port 7005 daemonize yes pidfile /data/7005/redis.pid loglevel notice logfile "/data/7005/redis.log" dbfilename dump.rdb dir /data/7005 protected-mode no cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes EOF
启动节点:
redis-server /data/7000/redis.conf redis-server /data/7001/redis.conf redis-server /data/7002/redis.conf redis-server /data/7003/redis.conf redis-server /data/7004/redis.conf redis-server /data/7005/redis.conf
ps -ef |grep redis
root 8854 1 0 03:56 ? 00:00:00 redis-server *:7000 [cluster]
root 8858 1 0 03:56 ? 00:00:00 redis-server *:7001 [cluster]
root 8860 1 0 03:56 ? 00:00:00 redis-server *:7002 [cluster]
root 8864 1 0 03:56 ? 00:00:00 redis-server *:7003 [cluster]
root 8866 1 0 03:56 ? 00:00:00 redis-server *:7004 [cluster]
root 8874 1 0 03:56 ? 00:00:00 redis-server *:7005 [cluster]
将节点加入集群管理
redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 \ 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
集群状态查看
集群主节点状态
redis-cli -p 7000 cluster nodes | grep master
集群从节点状态
redis-cli -p 7000 cluster nodes | grep slave
14.3 集群节点管理
增加新的节点
mkdir /data/7006 mkdir /data/7007
cat > /data/7006/redis.conf <<EOF port 7006 daemonize yes pidfile /data/7006/redis.pid loglevel notice logfile "/data/7006/redis.log" dbfilename dump.rdb dir /data/7006 protected-mode no cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes EOF cat > /data/7007/redis.conf <<EOF port 7007 daemonize yes pidfile /data/7007/redis.pid loglevel notice logfile "/data/7007/redis.log" dbfilename dump.rdb dir /data/7007 protected-mode no cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes EOF
redis-server /data/7006/redis.conf redis-server /data/7007/redis.conf
添加主节点:
redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000
转移slot(重新分片)
redis-trib.rb reshard 127.0.0.1:7000
进入分片界面:
计算:
16384/节点数 计算每个节点上应有的槽点数
在交互界面填入该值。
下一步:选择all 意思为新节点的槽点来自其他所有节点。
下一步交互界面:yes
即可。
添加一个从节点
redis-trib.rb add-node --slave --master-id 8ff9ef5b78e6da62bd7b362e1fe190cba19ef5ae 127.0.0.1:7007 127.0.0.1:7000
14.4 删除节点
将需要删除节点slot移动走
redis-trib.rb reshard 127.0.0.1:7000
49257f251824dd815bc7f31e1118b670365e861a
127.0.0.1:7006
0-1364 5461-6826 10923-12287
1365 1366 1365
删除一个节点
删除master节点之前首先要使用reshard移除master的全部slot,然后再删除当前节点
redis-trib.rb del-node 127.0.0.1:7006 8ff9ef5b78e6da62bd7b362e1fe190cba19ef5ae
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
redis集群搭建,5.0以上版本,5.0以下需要安装ruby。(未开启哨兵模式)
1。准备redis节点,并安装redis:(因为redis集群为去中心化设计,至少得6个节点,3主3从,保证投票可用主。此处虚拟机单节点伪集群)
创建集群配置以及数据目录:
mkdir /data/redis_cluster mkdir /data/redis_cluster/700{0..5}
在集群总目录下生成各个节点的配置(注:此处为伪集群所以一个目录生成多个节点的配置,多节点需在各个节点上配置)
mkdir 7000 7001 7002 7003 7004 7005(此处为生成伪集群六个节点的配置目录)
将源码包内生成的redis.conf文件拷贝到以上各个目录中:
cp redis.conf ../redis_cluster/7000/ cp redis.conf ../redis_cluster/7001/ cp redis.conf ../redis_cluster/7002/ cp redis.conf ../redis_cluster/7003/ cp redis.conf ../redis_cluster/7004/ cp redis.conf ../redis_cluster/7005/
(以上可以更改一个文件其余使用该文件修改端口即可)
根据目录修改相应的配置:
举例模板为:
port 7000 //端口7000,7002,7003
bind 本机ip //默认ip为127.0.0.1 需要改为其他节点机器可访问的ip 否则创建集群时无法访问对应的端口,无法创建集群
daemonize yes //redis后台运行
pidfile /var/run/redis_7000.pid //pidfile文件对应7000,7001,7002
cluster-enabled yes //开启集群 把注释#去掉
cluster-config-file nodes_7000.conf //集群的配置 配置文件首次启动自动生成 7000,7001,7002 把注释#去掉
cluster-node-timeout 15000 //请求超时 默认15秒,可自行设置 把注释#去掉
appendonly yes //aof日志开启 有需要就开启,它会每次写操作都记录一条日志
修改端口:
sed -i 's/7000/7001/g' ../7001/redis.conf sed -i 's/7000/7002/g' ../7002/redis.conf sed -i 's/7000/7003/g' ../7003/redis.conf sed -i 's/7000/7004/g' ../7004/redis.conf sed -i 's/7000/7005/g' ../7005/redis.conf
启动相关服务:
/usr/local/redis/bin/redis-server /data/redis_cluster/7000/redis.conf /usr/local/redis/bin/redis-server /data/redis_cluster/7001/redis.conf /usr/local/redis/bin/redis-server /data/redis_cluster/7002/redis.conf /usr/local/redis/bin/redis-server /data/redis_cluster/7003/redis.conf /usr/local/redis/bin/redis-server /data/redis_cluster/7004/redis.conf /usr/local/redis/bin/redis-server /data/redis_cluster/7005/redis.conf
检查服务:
ps -ef | grep redis netstat -anptl | grep redis
创建集群
原命令 redis-trib.rb 这个工具目前已经废弃,使用redis-cli (5.0之前版本使用redis-trib.rb)
/usr/local/redis/bin/redis-cli --cluster create --cluster-replicas 1 192.168.75.33:7000 192.168.75.33:7001 192.168.75.33:7002 192.168.75.33:7003 192.168.75.33:7004 192.168.75.33:7005
然后输入:yes确定等集群创建
出现如下字样表示集群创建成功:
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered
验证集群:
/usr/local/redis/bin/redis-cli -c -h 192.168.75.15 -p 7000(注意-c选项启用集群链接。) cluster info cluster nodes
显示集群信息,正常输出则集群成功。
缓存穿透
访问一个不存在的key,缓存不起作用,请求会穿透到DB,流量大时DB会挂掉。
解决方案
采用布隆过滤器,使用一个足够大的bitmap,用于存储可能访问的key,不存在的key直接被过滤;
访问key未在DB查询到值,也将空值写进缓存,但可以设置较短过期时间。
缓存雪崩
大量的key设置了相同的过期时间,导致在缓存在同一时刻全部失效,造成瞬时DB请求量大、压力骤增,引起雪崩。
解决方案
可以给缓存设置过期时间时加上一个随机值时间,使得每个key的过期时间分布开来,不会集中在同一时刻失效。
缓存击穿
一个存在的key,在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到DB,造成瞬时DB请求量大、压力骤增。
解决方案
在访问key之前,采用SETNX(set if not exists)来设置另一个短期key来锁住当前key的访问,访问结束再删除该短期key。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++