Redis相关知识

72 阅读8分钟

一:Redis数据类型,项目中应用场景****

redis的5种数据类型****

String类型

List类型

Set类型

ZSet类型

Hash类型

二:Redis雪崩,穿透,击穿****

雪崩(是redis中在同一时间的大量的key失效)****

原因:****

造成雪崩的原因:比如说淘宝双十一,很多用户同时发送请求,造成很高的并发,因为为了提高搜索效率,会将数据存到redis中,但是假如redis的超时时间是三个小时,正好此时redis的缓存都过期了,也就是redis缓存key同一时间大量失效,那么很多高并发的请求就直接全部打到数据库中,而数据库同一时间解决不了那么多请求,而导致数据库挂掉。这个就是雪崩造成的原因

解决方案:****

1:可以使用分布式锁,单机版使用本地锁

当突然有大量的请求到数据库服务器时候,进行请求限制,保证只有一个线程(请求操作)。否则进行排队等待(集群分布式锁,单机本地锁)。减少数据库服务器的吞吐量,但是这个方法效率较低

2.redis集群部署

redis一般都是集群部署,我们把热点的key,放到不同的节点上去,让热点的缓存平均的分布在不同的redis的节点上

3.均摊分配redis key的失效时间

不让在同一时间失效,不同key失效时间不同

4设置redis的key的超时时间永不过期

穿透(这个其实都是恶意用户,其实就是redis和数据库都没有这个数据)****

原因:****

key对应的数据在redis中并不存在,每次针对次key的请求从缓存中获取不到,请求都回到数据库,从而可能压垮数据库。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若是黑客利用此漏洞进行攻击可能压垮数据库

解决方案****

1.缓存空对象,是指在数据库没有命中的情况下,对key进行set(key,null)将值设置为null

但是这样也会出现两个问题。第一:value为null不代表不占用内存空间,空置做了缓存,意味着redis层中存了更多的键,需要更多的内存空间,解决办法是设置一个较短的过期时间,让其自动剔除。第二:redis和数据库的数据会有一段时间窗口的不一致,可能会对业务有一定影响。例如过期时间设置为5分钟,如果此时数据库修改这个数据,那么这段时间就会出现数据库和redis的数据不一致的问题,此时可以利用消息系统或者其他方式清除掉缓存层中的空对象

2.布隆过滤器拦截

在访问redis和数据库之前,将存在的key用布隆过滤器提前保存起来,做第一层拦截,当收到一个对key请求时先用布隆过滤器验证key是否存在,如果存在在进入redis,数据库

布隆过滤器实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。他的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难

3.对前端请求参数进行安全性校验,如果请求数据不合法,直接return掉

击穿(是redis中就是同一时间,大量的请求去访问redis这个key)****

原因:****

当大量的请求访问redis缓存中一个热点的key,当key的缓存没有失效的情况下,可以正常返回数据,但是key的过期时间到了,缓存失效,那么大量的请求访问从redis中查询不到数据,就会直接查询数据库,造成击穿redis(其实就是击穿某个热点的key)

解决方案****

1.最直接暴力的就是直接设置热点数据的key永不过期,但是这个不好,因为是热点数据,不可能一直是热点数据,而且设置key永不过期会造成redis内存占用的问题

2.如果是单体应用就可以使用分布式锁使用分布式的互斥锁,他的原理是当大量用户访问redis的热点数据,当redis有数据是正常返回,但热点数据过期时,大量的请求就会访问数据库,此时我们在大量请求访问数据库之前加上分布式锁,此时只能有一个线程访问数据库,当这个线程查询到数据后,会把数据重新写道redis中,让没有抢到锁的线程睡眠几秒,然后在重新从redis中查询,就解决了击穿问题

三:Redis的持久化(RDB,AOF)****

RDB(其实就是快照,恢复快照的意思)****

RDB全称Redis Database Backup file(Redis数据备份文件),这个是写入磁盘的,也被称为数据快照,其实就是一个快照,简单来说就是把内存中的数据存到磁盘中。当Redis实例出现故障后,可以从磁盘读取快照,恢复数据,但是恢复的数据都是快照之前的,会造成数据丢失,快照文件称为RDB文件,默认是保存在当前运行目录下。

RDB持久化在四种情况下会执行

1.执行save命令

2.执行bgsave命令

3.Redis停机时

4.触发RDB条件时

RDB方式bgsave的基本流程:

1.fork主进程得到一个子进程,共享内存空间

2.子进程读取内存数据并写入新的RDB文件

3.用新RDB文件替换旧的RDB

RDB会在什么时候执行?save 60 1000代表什么含义

1.默认是服务停止时

2.代表60秒内至少执行1000次修改则触发RDB

RDB的缺点

1.RDB执行间隔时间长,两次RDB之间写入数据有丢失的风险

2.fork子进程,压缩,写出RDB文件都比较耗时

AOF****

AOF全程为Append Only File(追加文件)。Redis处理的每一个命令都会记录在AOF文件,可以看做是命令日志文件。这个是默认关闭的,需要修改redis.conf来手动开启

AOF其实相当于记录操作日志,但是每一次记录一次操作,会使得AOF文件越来越大,这是我们可以通过bgrewriteaof去重写AOF文件

Redis也会在触发阈值时自动去重写AOF文件,阈值也可以通过redis.conf中配置

如果:****

RDB和AOF同时开启的情况下,redis会优先读取AOF文件,因为AOF的数据更加完整!!

四:Redis集群和哨兵****

Redis的集群同步原理****

全量同步:****

主从第一次简历连接时,会执行全量同步,将master节点的所有数据都拷贝到slave节点流程:

 

总共分为三个阶段

第一阶段

1.0.执行replicaof命令,建立连接

1.1.请求数据同步

1.2.判断是否为第一次同步

1.3.是第一次同步,返回master的数据版本信息(就是主节点的版本信息)

1.4.从节点保存版本信息

第二阶段

2.1.master执行bgsave ,生成RDB文件

2.1.1.记录RDB期间的所有命令到repl_baklog文件中

2.2.master发送RDB文件给slave

2.3.清空本地数据加载RDB文件

第三阶段

3.1.master发送repl_baklog中的命令

3.2.slave执行接收到的命令

整个过程就是redis集群的全量同步的原理

注意:master是通过判断replid来判断是否为第一次连接,发现id不一致就拒绝全量同步;

增量同步:****

大量同步需要先做RDB,然后将RDB文件通过网络传输到slave,成本太高。因此除了第一次做全量同步,其他大多数时候slave与master都是增量同步即可

第一阶段

1.0.slave重启

1.1.rsync replid offset

1.2.判断请求replid是否一致

1.3.不是第一次,回复continue

第二阶段

2.1.master去repl_baklog中获取offset后的数据

2.2.master发送offset后的命令

2.3.slave执行命令

Redis哨兵****

哨兵的结构图

 

哨兵的作用:

1.监控:Sentinel会不断检查master和slave是否按预期工作

2.自动故障恢复:如果master故障,Sentinel会将一个slave升级为master。当旧的master恢复后,也是以新的master为主

3.通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新的信息推送Redis的客户端

五:如何保证数据库和Redis数据的一致性(使用Canal)****

Canal是阿里巴巴旗下的一款开源项目,基于java开发是用来实现。

1.canal服务器伪装成mysql的从节点,订阅mysql的binlog二进制文件

2.当mysql主节点binlog发生改变时,会通知给canal服务端

3.canal服务器将改变的数据转换成json数据发送给canal客户端

3。在canal客户端中,将数据异步的写入到redis中