深度长文整理-Redis进阶(三)

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 深度长文整理-Redis进阶(三)

十、主从复制#


概念:和MySQL的主从复制的概念大同小异,分成leader节点和follower节点,主节点承接线上的写流量,从节点承接线上的读流量为主库分流减压,从库的数据从主库中同步过来


主从复制的作用:

  1. 理论上主库从库的数据是需要保持的,这也是一种数据冗余热备份的机制
  2. 故障恢复:当leader节点出现故障时,可以由从节点提供服务,保证应用的可用性
  3. 负载均衡:在主从复制的接触上,可以将客户端的读写不同类型的流量分摊到不同的机器上,分流减压
  4. 主从复制+哨兵,构建高可用的redis集群,解决了单点故障问题


十一、集群搭建及小实验#


redis默认自己就是一个主库,所以我们搭建主从架构的redis,只需要配置Redis从库。



11.1、架构一:一主两从#


下面搭建这样的一主两从的redis集群



role ip port
主库 xxx 16379
从库 xxx 16378
从库 xxx 16377


如果是在一台服务器上启动多台Redis,需要修改一下配置文件中的端口、pid文件名、日志名、dump.db名


启动三台redis



让16378、16377认16379为leader,执行如下命令:



搭建完主从环境之后,查看是否可以从slave中写入数据:


# 结果很明显,不能写入
127.0.0.1:16378> set k1 v0
(error) READONLY You can't write against a read only replica.


MySQL中只要你不设置从库read only,从库也是可以写入的并产生自己的binlog的


测试:从master写入,从slave读出



测试:主机宕机,slave有什么表现


主机宕机后,从库的role依然是slave,并且显示master的状态为down



测试:主机宕机后又重启了,slave有什么表现


主机重启后,slave会重连主机,主机的状态为up,salve可以正常在主库上同步数据



测试:从机宕机,然后有新数据写到了主库,从机再重启问:重启后的从机能不能获取到她宕机期间主库的增量数据?


答案是:获取不到了,因为如果是通过命令行搭建的主从,从库一旦重启,角色会变回master



如果这时再把16378变成16379的从库,问能不能获取到增量数据呢?



全量复制和增量复制


从库第一次连接到主库上肯定会进行一次全量复制,即:master会启动后台的存盘进程,同时收集所有用于修改数据集的命令,在后台完成同步,然后将整个数据文件发送给slave,让slave完成一次数据的全量复制


除第一次复制数据之外的主从复制都是增量复制,即master仅仅会将收到的增量写命令发送给slave。


11.2、架构二#



其中的17378既是Master又是Slave

对于16377来说,它确实认了16378为主,但是16378本身又是16379的slave,所以他们之间数据同步的走向是 : 16379 --> 16378 --> 16377 ,对于16378来说,即使有实例认它当master,它依然是不能写



如果主库16379宕机了,16378的状态依然是slave,并且它能察觉master已经挂了,执行 slave no one, 可以将自己提升为master。 在整个过程中,16377不受影响

即使旧master开机重启了,旧的master依然是master,也不能自动的加入到 16377 16378集群中



11.3、架构三:Sentinel#


上面的两种架构模式中,主库挂了之后都需要人为的去选举一个的新的master来承接读流量


redis2.8之之后,提供了哨兵模式:哨兵监控到当主服务器挂了,发起投票选新主库,实现自动的完成选主,承接线上写流量,完成止损


哨兵作为一个独立的进程存在,原理是:哨兵通过发送命令和redis服务器交互,从而监控运行整个集群中的多个Redis实例



Redis的哨兵在Redis 的安装目录下可以找到



为了防护哨兵出现单点故障,所以通常使用多个哨兵对集群进行监控


集群中的每个哨兵彼此相互监控,每个哨兵也都监控着集群中的所有Redis实例



主观下线和客观下线

当一个哨兵发现master不可用时,系统不会马上进行failover,仅仅是这一个哨兵主观意义上认为这个master不可用,这时如果其他的哨兵也来探测master,并且大部分的哨兵都主观认为master确实不可用了,哨兵们就会投票在slave中选出一个当得票最多的slave作为新的master。进行failover操作。


通过发布订阅的模式,哨兵告诉自己监控的那些服务器将master切换为刚刚的票最多的那个实例,这个过程就叫做客观下线


集群搭建

首先是创建一主二从的redis集群, 此处省略,参照上面架构1部分即可

编写sentinel的配置文件,配置文件的名称、配置项不能写错~


# myredis1 监控的这个redis实例啥
# 127.0.0.1 监控的这个redis实例的ip
# 16379 监控的这个redis实例的端口
# 1 监控的这个redis实例的挂了后,自动投票选主
sentinel monitor myredis1 127.0.0.1 16379 1


启动sentinel



这样,当master宕机后,哨兵会自动选择一个新的slave作为新主,主库重启后,sentinel会将其作为slave自动加入到现有的redis集群中


更多更详细的sentinel配置文件可以看看这个博文:https://www.cnblogs.com/heroinss/p/10340925.html


十二、缓存穿透、缓存击穿、雪崩#


缓存穿透


比如这种应用场景:使用redis缓存用户信息,当有新用户注册时先将用户的信息写入Mysql,然后写入Redis。有修改操作时,修改完MySQl中的数据后,同步的也会修改Redis中的数据,而且我们也没有给Redis中的key设置过期时间。(这就意味着:数据库中有指定的KV的信息的话,缓存中也会有。那当用户查询时缓存中没有的话,说明数据库中99.999%也不会有)


这时候有大量的请求去访问MySQL中都没有都数据时,请求先打向了Redis,Redis中肯定也没有存储用户查询的数据,所以大量的请求一下子打到了数据库上,瞬间击垮数据库,这种现象称为缓存穿透。


解决方案:

布隆过滤器:



布隆过滤器可以理解成一个bit数组,数组中每一个非0即1

客户端的请求统一先打向布隆过滤器,布隆过滤器放在应用的控制层,布隆过滤器中存在多个hash函数,分别对这个key进行hash得到hashcode,然后将hashcode%数组长度,将算出来的下标标记为1。


key以此经过所有hash,再%size算出的下标对应的值,只要存在一个不为1的数,我们就认为key没在缓存中,直接丢弃用户的这次请求,符合要求把请求打向Redis。从而避免这个请求对底层存储的查询压力。


缓存空对象:


当用户查询的时候,如果发现缓存中没有,就往缓存中放置一个空的对象,然后返回给用户这个控对象,也能避免用户的请求直接打向数据库。


缓存击穿:


缓存击穿指的是Redis中确确实实存在用户查询的key,但是呢用户的访问频率太猛烈了,导致Redis扛不住挂了,导致大量的请求直接打向数据库,或者当某一个key的过期时间到了的瞬间,大量的请求打向数据库导致数据库直接挂了


解决方案:


设置key永不过期

加互斥锁:对这个查询操作添加分布式锁,将原来的大并发直接访问缓存转换成了并发获取分布式锁,只有获取到分布式锁后才能去查询缓存。


雪崩:


比我们启动redis进行一些数据预热,就是将一些数据库中的数据提前导入到redis中,然后给这些数据设置了过期时间。


抢购时间一到系统迎来了一大批并发,但是由于缓存中的数据充足,所以能扛住这波并发。一段时间后,redis中的key集中式的过期了,这时再来一大批并发请求可能就直接将redis打垮。redis挂了后,大量的请求直接打向MySQL,导致MySQL跟着雪崩式的垮掉


解决方法:

异地多活,添加redis的实例的数量

加分布式锁

在应用和缓存之间添加消息中间件做缓冲

合理为不同的key设置不同的过期时间,放置缓存中的key出现集中式过期的情况

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
7月前
|
存储 缓存 Java
【Spring原理高级进阶】有Redis为啥不用?深入剖析 Spring Cache:缓存的工作原理、缓存注解的使用方法与最佳实践
【Spring原理高级进阶】有Redis为啥不用?深入剖析 Spring Cache:缓存的工作原理、缓存注解的使用方法与最佳实践
|
7月前
|
NoSQL Java Redis
Redis进阶-lua脚本
Redis进阶-lua脚本
117 0
|
7月前
|
存储 NoSQL Java
Redis进阶-细说分布式锁
Redis进阶-细说分布式锁
80 0
|
7月前
|
NoSQL Redis
Redis进阶-bind参数详解
Redis进阶-bind参数详解
421 0
|
7月前
|
NoSQL Java Redis
Redis进阶-Jedis以及Spring Boot操作 Redis 5.x Cluster
Redis进阶-Jedis以及Spring Boot操作 Redis 5.x Cluster
112 0
|
7月前
|
NoSQL 算法 Redis
Redis进阶-Redis对于过期键的三种清除策略
Redis进阶-Redis对于过期键的三种清除策略
104 0
|
6月前
|
NoSQL 数据可视化 Java
rodert单排学习redis进阶【白银一】
rodert单排学习redis进阶【白银一】
30 0
|
6月前
|
NoSQL Redis 数据库
rodert单排学习redis进阶【青铜】2
rodert单排学习redis进阶【青铜】
35 0
|
6月前
|
缓存 NoSQL Java
rodert单排学习redis进阶【青铜】1
rodert单排学习redis进阶【青铜】
43 0
|
6月前
|
NoSQL 关系型数据库 MySQL
Redis进阶-select 1. /xxx 切换数据库DBSIZE- 获取当前数据库中的key的个数flushdb-删除当前数据的所有keyflushall-删除所有表的所有库Re
Redis进阶-select 1. /xxx 切换数据库DBSIZE- 获取当前数据库中的key的个数flushdb-删除当前数据的所有keyflushall-删除所有表的所有库Re