redis--主从复制,哨兵模式,缓存穿透,缓存雪崩

一、主从复制

1.为什么会有主从复制

通过持久化功能,redis保证了即使在服务器重启的情况下数据也不会丢失,但是如果由于数据存储在一台服务器上的,如果这台服务器出现故障,比如硬盘坏了,也会导致数据的丢失。
所以为了避免这种故障,我们需要将数据复制到多份部署在多台不同的服务器上,即使有一台服务器出现故障,其他服务器依然可以继续提供服务。
这就要求当一台服务器上的数据更新后,自动将更新的数据同步到其他服务器上,这时候就用到了redis的主从复制,实现redis的高可用。
一个master(主机)可以拥有多个slave(从机),一个slave只对应一个master

2.主从复制的作用

读写分离:master写、slave读,提高服务器的读写负载能力。
负载均衡:基于主从结构,配合读写分离,由slave分担master负载,并根据需求的变化,改变slave的数量,通过多个从节点分担数据读取负载,大大提高redis服务器并发量与数据吞吐量。
故障恢复:当master出现问题时,由slave提供服务,实现快速的故障恢复。
数据冗余:实现数据热备份,是持久化之外的一种数据冗余方式。
高可用基石:基于主从复制,构建哨兵模式与集群,实现redis的高可用

3.复制原理

从机启动成功连接到主机后会发送一个sync同步命令,主机接到命令,启动后台的存盘进程,同时所有接收到的用户修改数据集命令,在后台进程执行完毕之后,主机将传送整个数据文件到从机,并完成第一次完全同步。
全量复制
从机服务在接收到数据库文件数据后,将其存盘并加载到内存中。
增量复制
主机继续将新的所有收集到的修改命令依次传递给从机,完成同步。
但是只要是从机重新连接主机,一次完全同步(全量复制)将自动执行

二、哨兵模式

1.概述:

主从切换技术的方法是:当服务器宕机后,需要手动一台从机切换为主机,这需要人工干预,不仅费时费力而且还会造成一段时间内服务不可用。所以有了哨兵模式。

2.单哨兵模式

哨兵模式是一种特殊的模式,首先redis提供了哨兵的命令,哨兵是一个独立的进程,它会独立运行通过发送命令,等待redis服务器响应,从而监控多个redis服务器

这里的哨兵有两个作用
1.通过发送命令,来监控redis服务器的运行状态。
2.当检测到主机宕机,会自动将某个从机切换为主机,然后通过发布订阅模式来通知其他服务器修改配置文件进行连接。

3.多哨兵模式

然而一个哨兵对redis服务器的进行监控,当这个哨兵出现问题怎么办,因此我们可以使用多个哨兵来进行监控,每个哨兵之间也会进行监控,这样就形成了多哨兵模式。
在这里插入图片描述

假设主服务器宕机,哨兵先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象称为主观下线,当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵执行failover故障转移操作,切换成功后,就会通过发布订阅让各个哨兵把自己监控的从服务器链接到新的主机上去。

4.优缺点

优点
哨兵模式就是主从复制的升级,手动到自动;
主从可以切换,故障可以转移,系统的可用性就会更好
缺点
redis不好在线扩容,集群容量一旦达到上限,在线扩容就十分麻烦。
实现哨兵模式的配置其实是很麻烦的,里面有很多的选择。

5.哨兵模式的全部配置

// Example sentinel.conf
// 哨兵sentinel实例运行的端口 默认是26379
port 26379
//哨兵sentinel的工作目录
dir /tmp
//哨兵sentinel监控的redis主节点的 ip port
// master-name  可以自己命名主节点名字 稚嫩由字母A-z数字0-9“.-_”这三个组成
//quorum 当这些quorum个数sentinel哨兵认为master主节点失联,那么这时,客观上认为主节点失联了
sentinel monitor <master-name> <ip> <redis-port> <quorum>

//当在redis实例中开启了requirepass foobared授权密码 这样所有连接redis实例的客户端都要提供密码
//设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
sentinel auth-pass <master-name> <password>

//指定多少毫秒后主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒
sentinel down-after-milliseconds <master-name> <milliseconds>

//这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行同步。
//这个数字越小,完成failover所需时间就越长,但如果这个数字越大,就意味着越多的slaver因为replication而不可用。
//可以通过将这个值设为 1 来保证每次只有一个slave  处于不能处理命令请求得状态
sentinel parallel-syncs <master-name> <numslaves>

//故障转移的超时时间 failover-timeout 可以用在以下方面
/*
1.同一个sentinel对用一个master两次failover之间的间隔时间。
2.当一个slave从一个错误的master那里同步数据开始计算的时间。直到slave被纠正为向正确的master那里同步数据时
3.当想要取消一个正在进行的failover所需要的时间。
4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来
*/
//默认三分钟
sentinel failover-timeout <master-name> <milliseconds>

//SCRIPTS EXECUTION
//配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员
//对于脚本运行结果有以下规则:
/*
1.若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
2.若脚本执行后返回2,或者一个比2更高的一个返回值,将本将不会重复执行。
3.若将本在执行过程中由于收到了系统中断信号被终止了,则同返回值为1时的行为相同。
4.一个脚本最大的执行时间是60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行
*/

//通知型脚本:当sentinel有任何警告级别的事件发生时(比如redis实例主观失效和客观失效),将会调用这个脚本
//这时这个脚本应该通过邮件,sms等方式取通知系统管理员关于系统不正常运行的信息,调用该脚本时,将传递给脚本两个参数:
//一个是事件的类型
//一个是事件的描述。
//如果sentinel.conf配置文件中配置了这个脚本的路径,那么必须保证这个脚本存在于这个路径,并且可执行。
sentinel notification-script <master-name> <script-path>

//客户端重新配置主节点参数脚本
//当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。
//以下参数将会在调用脚本时传给脚本:
//<master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
//目前<state>总是“failover”,
//<role>时leader或者observer中的一个
//参数 from-ip from-port to-ip to-port 是用来和旧的master和新的master通信的
//这个脚本应该是通用的,能被多次调用,不是针对性的。
sentinel client-reconfig-script <master-name> <script-path>

三、缓存穿透

1.什么是缓存穿透

用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。

2.解决方案

布隆过滤器
原理
很简单首先也是对所有可能查询的参数以hash形式存储,当用户想要查询的时候,使用布隆过滤器发现不在集合中,就直接丢弃,不在对持久层查询。

1.布隆过滤器是一个由很长的bit数组和一系列的哈希函数组成的。
2.数组的每个元素都只占1bit空间,并且每个元素只能为0或1
3.布隆过滤器还拥有k个哈希函数,当一个元素加入布隆过滤器时,会使用k个哈希函数对其进行K次计算,得到k个哈希值,并且根据得到的哈希值,在数组中把对应下标的值置为1.
4.判断某个数是否在布隆过滤器中,就对该元素进行k次的哈希计算,得到的值在数组中判断每个元素是否都为1,如果每个元素都为1,就说明这个值是在布隆过滤器中的

为什么会有误判

1.当插入的元素越来越多时,当一个不在布隆过滤器中的元素,经过同样规则的哈希计算之后,有可能浙西位置因为其他的元素先被置为1了。
2.所以布隆过滤器存在误判的情况,但是布隆过滤器判断某个元素不在布隆过滤器中,那么这个值就一定不在

缓存空对象
原理:
当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端的数据源;
该方法所产生的问题:

1.如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储跟多的键,因为这当中可能会有很多的空值的键;
2.即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致性,这对于需要保持一致性的业务会有影响。

四、缓存击穿

1.概述

缓存击穿,是指一个key非常热点,大并发的集中对这一个点进行访问,但是当redis中这个点再一个瞬间失效(缓存过期)了,那么这些大并发的访问都会直接请求数据库,给数据库瞬间造成极大的压力。

2.解决方案

1.设置热点数据永不过期
2.后台定义一个job(定时任务)专门主动更新缓存数据,比如,一个缓存中的数据过期时间是30分钟,那么job每隔29分钟定时刷新数据(将从数据库中查到的数据更新到缓存中),这种方案比较容易理解,但是会增加系统的复杂度。比较适合哪些ke相对固定,cache粒度较大的业务,key比较分散的则不太适合,实现起来也比较复杂。
3.使用分布式锁,保证在高并发情况下每次同时只有一个线程去查询数据库,其他线程没有获得分布式锁的权限,其余的进行等待,这样就将高并发的压力转移到了分布式锁上。

五、缓存雪崩

1.概述

缓存雪崩指的是缓存层出现了错误,不能正常工作了。于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。

在这里插入图片描述

2解决方案

1.搭建集群,既然redis有可能挂掉,那我多增设几台redis,这样一台挂掉之后其他的还可以继续工作。
2.限流降级,在缓存失效后,通过加锁或者队列来空值读数据库写缓存的线程数量。比如对某一个key只允许一个线程查询数据和写缓存,其他线程等待。
3.数据预热,在正式部署前,我先把可能的数据预先访问一边,这样部分可能大量访问的数据就加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值