目录:
Redis从入门到精通(一):缓存
Redis从入门到精通(二):分布式锁以及缓存相关问题
Redis从入门到精通(三):Redis持久化算法以及内存淘汰策略
Redis从入门到精通(四):Redis常用数据结构以及指令
Redis从入门到精通(五):Redis6整合SpringBoot2.x+Mybatis+SpringCache
Redis从入门到精通(六):Redis高可用原理
Redis从入门到精通(七):跳跃表的简介与实现
Redis从入门到精通(八):Redis新特性
高可用
什么是高可用?
我们在第一章就提到了CAP原则,其中的A就是可用性,高可用自然就是high availability.
一般来说,高可用是指某个或者某些节点挂掉后,整个程序依然可以正常运行。也就是我们需要对系统进行集群处理,当然,实现高可用的途径不只是集群,比如这章会提到许多方法共同去保证一个系统的高可用。
Redis高可用
主从复制与读写分离
主从架构是高可用基础,以后的集群也往往是根据主从原理构建的。当然现在提出了无中心节点的架构,其实也是主从原理的延伸。
看过我之前翻译的谷歌论文:GFS的都清楚,主节点承担主要的写操作,读操作通过负载均衡方法选择主从节点。且从节点定期会复制主节点数据,这样一来,主节点宕机后,从节点依然可以工作。此时从节点可以开启写操作。
当然了,从节点会有很多,并非只有1个,这时候我们就会通过选举机制选择新的主节点。
主从复制方法有两种:
- 全量复制
- 在master开启后,会在后台生成rdb文件
- 从节点连接时,会全量复制rdb文件
- 从节点读取RDB文件
- 增量复制
- 全量复制结束后,主节点收到的数据会以增量的形式发给从节点,以达到同步效果(根据同步策略)。
同步特点:
- 非阻塞。同步期间,可以进行新命令的操作
- 从节点不主动对数据做删除处理,只有等到主节点key过期后,主节点会发送命令到从节点,从节点删除key
- 从节点间也可以收到其他从节点的信息
加速同步:有时候,在磁盘速度比较慢的情况下,我们可以开启配置文件,输入配置:repl-diskless-sync yes
,这种方法不会讲RDB文件写入磁盘,而是在内存中直接向网络传送,不会经过磁盘。
加入某个节点挂了重连,之前同步过的数据不用再同步,使用PSYNC
命令就可以进行未同步的命令复制。
Redis主从架构实战
- 新建目录
mkdir -p /data/redis/master/data mkdir -p /data/redis/slave1/data mkdir -p /data/redis/slave2/data
- 对配置文件进行更改,我们首先修改主节点文件
vim /data/redis/master/data/redis.conf
再对从节点配置文件进行修改。bind 0.0.0.0 daemonize yes requirepass 123456 port 9000 #如果是本机部署多redis,必须修改端口号,否则端口只能绑定一个服务 logfile "/usr/local/redis/log/redis_master.log" dbfilename test.rdb dir /usr/local/redis/data save 10 1 rdbcompression yes rdbchecksum yes appendonly yes appendfilename "appendonly_master.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes masterauth 123456
bind 0.0.0.0 daemonize yes requirepass 123456 port 9001 logfile "/usr/local/redis/log/redis_slave1.log" dbfilename test.rdb dir /usr/local/redis/data save 10 1 rdbcompression yes rdbchecksum yes appendonly yes appendfilename "appendonly_master.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes masterauth 123456 replicaof 42.193.119.84 9000 ##主节点的地址和端口
bind 0.0.0.0 daemonize yes requirepass 123456 port 9002 logfile "/usr/local/redis/log/redis_slave2.log" dbfilename test.rdb dir /usr/local/redis/data save 10 1 rdbcompression yes rdbchecksum yes appendonly yes appendfilename "appendonly_master.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes masterauth 123456 replicaof 42.193.119.84 9000 ##主节点的地址和端口
- 开启服务,先主后从。
cd /usr/local/redis/bin ./redis-server /data/redis/master/data/redis.conf ./redis-server /data/redis/slave1/data/redis.conf ./redis-server /data/redis/slave2/data/redis.conf
- 分别查看9000、9001、9002端口是否开启服务
lsof -i:9000 lsof -i:9001 lsof -i:9002
也可以用ps -ef | grep redis
查看
- 进行登录访问redis,略。
- 查看信息
info Replication
- 测试。首先在主节点进行set操作
然后在从节点进行get
在从节点set操作
Redis哨兵
我们在上一节配置成功了主从,但是当某一个节点挂掉后,需要我们人工设置新的主节点。假如夜里3点挂了,还要把程序猿叫起来改bug,程序猿是很懒的,就想出了办法,利用哨兵机制自动选举新的主节点。
实际上这些玩意都是人家google在2003年GFS里玩剩下的,别的技术拿来再用,计算机就是老一套,相互抄袭。在计算机某一领域有稍微的了解后,就会发现其他领域用的也是一样的内容。接下来我们详细谈谈哨兵机制。
哨兵工作原理
Redis利用一个独立的进程,去探测各个节点是否有响应。当然是通过网络传输的,既然是网络,就可能有一定的误判性,以后再说。在Redis里,这玩意叫做哨兵(Sentinel),在SpringCloud或者是GFS里,它叫做心跳机制。
当哨兵检测到主节点挂掉,会自动选举出新的主节点,并修改各个从节点的配置文件。
哨兵任务:
- 监控状态(monitoring),心跳机制,PING
- 汇报(Notification),告诉维护人员工作状态是否正常
- 故障转移(Automatic Failover),选举新的主服务器,更改配置文件。
通常情况下,哨兵也是集群部署,并且相互检测。
多哨兵下线模式:
- 主观下线(subjectively down,SDOWN)
- 单个哨兵对服务器下线进行判断
- 当服务器没有回应,哨兵会判断其下线
- 客观下线(objectively down, ODOWN)
- 多个哨兵进行交流判断
- 当某一个哨兵发现一个服务断掉,会向其他哨兵询问,当得到的结果是都认为其下线,则客观下线形成
- 一般指针对于主服务器
- 仲裁
- 一定数量的哨兵认为某个服务下线,即判断服务下线。数量一般取哨兵数量的一半+1。 n u m b e r = N s e n t i n e l 2 + 1 number = \frac{N_{sentinel}}{2}+1 number=2Nsentinel+1
- 主节点下线后,进行选举得到新的主节点
你看,即使是高可用,他也是会短暂丢失数据的。
哨兵实战
-
新增文件
touch /var/log/redis/sentinel_26379.log
touch /var/log/redis/sentinel_26380.log
touch /var/log/redis/sentinel_26381.log
没有文件夹先创建文件夹。 -
新增配置文件:
port 26379 bind 0.0.0.0 daemonize yes pidfile "/var/run/redis-sentinel-1.pid" logfile "/var/log/redis/sentinel_26379.log" dir "/tmp" sentinel monitor mymaster 42.193.119.84 9000 2 #最后的2是指宕机时多少哨兵判断成立 sentinel down-after-milliseconds mymaster 5000 sentinel auth-pass mymaster 123456 sentinel failover-timeout mymaster 30000
port 26380 bind 0.0.0.0 daemonize yes pidfile "/var/run/redis-sentinel-2.pid" logfile "/var/log/redis/sentinel_26380.log" dir "/tmp" sentinel monitor mymaster 42.193.119.84 9000 2 sentinel down-after-milliseconds mymaster 5000 sentinel auth-pass mymaster 123456 sentinel failover-timeout mymaster 30000
port 26381 bind 0.0.0.0 daemonize yes pidfile "/var/run/redis-sentinel-3.pid" logfile "/var/log/redis/sentinel_26381.log" dir "/tmp" sentinel monitor mymaster 42.193.119.84 9000 2 sentinel down-after-milliseconds mymaster 5000 sentinel auth-pass mymaster 123456 sentinel failover-timeout mymaster 30000
-
启动sentinel
./redis-server ../conf/sentinel-1.conf
./redis-server ../conf/sentinel-2.conf
./redis-server ../conf/sentinel-3.conf
-
登录sentinel
-
模拟宕机并查看日志
-
重启原主节点
Springboot整合Sentinel
这个很简单,就是在配置文件中添加:
Redis集群
什么是集群?
集群就是许多相同服务的节点通过高速网络集合在一起。
Redis集群可以解决单机Redis容量有限,或者单服务挂机问题。
Cluster数据分片与Hash槽
分区算法:
- Hash取模:对数据进行Hashcode计算,取模后得到的就是该key的分区
- 范围分片:确定key是否在某个范围来确定分区
- 一致性Hash分区(略复杂,暂时不涉及)
- 数据分片的hash槽(Redis用此方法)
Hash槽slot:
- Redis集群预先分配好16384个桶,当新的key来临时,计算 C R C 16 ( k e y ) m o d 16384 CRC16(key)mod16384 CRC16(key)mod16384的值来判断新的key在哪个桶内。
- 从节点无槽位,只有主节点有槽位。
- 用户根据集群数量分配每个节点有多少桶,加入有3个节点,那么每个节点的槽位若以平分的方式计算,为0-5460, 5461-10922,10923-16384分别存储在节点一,节点二,节点三中。
- 当加入新的节点,只需要重新分配槽即可。
集群原理以及搭建
一个集群一般是指多个节点,每个节点有一个主节点和一个或多个从节点。
首先,我们需要修改配置:
对于节点一:
bind 0.0.0.0
port 6381 #
daemonize yes
requirepass 123456
logfile "/usr/local/redis/log/redis-cluster-1.log"
dbfilename "redis_test.rdb"
dir "/usr/local/redis/data"
appendonly yes
appendfilename "appendonly1.aof"
masterauth 123456
cluster-enabled yes
cluster-config-file nodes-6381.conf
cluster-node-timeout 20000
cluster-announce-ip 42.193.119.84
cluster-announce-port 6381
cluster-announce-bus-port 16381
对于节点二:
bind 0.0.0.0
port 6382
daemonize yes
requirepass 123456
logfile "/usr/local/redis/log/redis-cluster-2.log"
dbfilename "redis_test2.rdb"
dir "/usr/local/redis/data"
appendonly yes
appendfilename "appendonly2.aof"
masterauth 123456
cluster-enabled yes
cluster-config-file nodes-6382.conf
cluster-node-timeout 20000
cluster-announce-ip 42.193.119.84
cluster-announce-port 6382
cluster-announce-bus-port 16382
以此类推。
清除之前的日志文件和RDB文件,否则会创建文件失败。
然后启动各个配置文件:
./redis-server ../conf/cluster/cluster-1.conf
./redis-server ../conf/cluster/cluster-2.conf
./redis-server ../conf/cluster/cluster-3.conf
./redis-server ../conf/cluster/cluster-4.conf
./redis-server ../conf/cluster/cluster-5.conf
./redis-server ../conf/cluster/cluster-6.conf
当前只是启动了节点,还未加入集群。
./redis-cli -a 123456 --cluster create 42.193.119.84:6381 42.193.119.84:6382 42.193.119.84:6383 42.193.119.84:6384 42.193.119.84:6385 42.193.119.84:6386 --cluster-replicas 1
其中,最后一个参数是指主从以
1
:
1
1:1
1:1的方式建立集群。
划线部分是指槽位的分配。
我们登录进去,查看一些信息:
./redis-cli -c -a 123456 -p 6381
cluster info
cluster nodes
他会重新定向,根据我们前文讲的方法。
整合Springboot
配置文件修改成这样就可以了。