redis 消息离线缓存_java-redis面试整理

本文深入探讨Redis在缓存、消息离线处理中的应用,详细解析Redis的数据类型、过期策略,特别是LRU算法的实现。同时,针对缓存雪崩、穿透问题提出解决方案,并详述Redis的RDB和AOF持久化机制,以及应对AOF文件损坏的方法。此外,还讨论了Redis的管道操作、双写一致性保证和并发竞争Key的处理策略,以及位图在用户签到等场景的应用。
摘要由CSDN通过智能技术生成

1. Redis的应用场景

  • 做缓存
  • 分布式锁

2. Redis支持的数据类型(必考)

支持string,list,set,sorted set,hash

3. zset跳表的数据结构(必考)4. Redis的数据过期策略(必考)

redis 提供 6种数据淘汰策略:

  • voltile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
  • volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
  • volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
  • allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
  • allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
  • no-enviction(驱逐):禁止驱逐数据

5. Redis的LRU过期策略的具体实现

  • Redis做法很简单:随机取若干个key,然后按照访问时间排序,淘汰掉最不经常使用的数据。为此,Redis给每个key额外增加了一个24bit长度的字段,用于保存最后一次被访问的时钟(Redis维护了一个全局LRU时钟lruclock:REDIS_LUR_BITS,时钟分辨率默认1秒)。
  • redis会基于​server.maxmemory_samples​配置选取固定数目的key,然后比较它们的lru访问时间,然后淘汰最近最久没有访问的key,maxmemory_samples的值越大,Redis的近似LRU算法就越接近于严格LRU算法

6. 如何解决Redis缓存雪崩,缓存穿透问题

1、缓存雪崩:我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时

失 效,请求全部转发到DB,DB瞬时压力过重雪崩。

方法:

过期时间设置分散(过期时间添加1-5分钟的随机时间)

2、缓存穿透:查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。

方法:

布隆过滤器或这在查询数据库后默认缓存一个定值

7. Redis的持久化机制(必考)

RDB持久化

某一个时刻将数据持久化到一个RDB快照文件中,所以RDB持久化也叫做快照持久化。

RDB文件创建:

1、SAVE命令会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间, 服务器不能处理任何命令请求

2、BGSAVE命令会派生出一个子进程,然后由子进程负责创建RDB文件,服务器进程(父进程)继续处理命令请求

save选项设置的默认条件如下所示:

save 900 1

save 300 10

save 60 10000

服务器在900s(即15分钟)之内,对数据库进行了至少1次修改

服务器在300s(即5分钟)之内,对数据库进行了至少10次修改

服务器在60s(即1分钟)之内,对数据库进行了至少10000次修改

只要满足以下3个条件中的任意1个,BGSAVE命令就会被执行:生成的RDB文件会根据Redis配置文件中的名称和路径来保存

载入RDB文件:

1、只有在AOF持久化功能处于关闭状态时,服务器才会使用RDB文件来还原数据。

2、如果服务器开启了AOF持久化功能,那么服务器会优先使用AOF文件来还原数据。

3、默认情况下,Redis服务器的AOF持久化功能是关闭的,所以Redis服务器在启动时会载入RDB文件,

4、服务器在载入RDB文件期间,会一直处于阻塞状态,直到RDB文件载入成功。

f8a9b4a2eef158f4b4eae972995a6395.png

AOF持久化

AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库数据的,默认情况下,AOF持久化功能是关闭的,如果想要打开,可以修改配置

AOF持久化的实现:

AOF文件重写并不需要对现有的AOF文件进行任何读取、分析或者写入操作,而是通过读取服务器当前的数据库数据来实现的。

AOF文件重写功能的实现原理为:

首先从数据库中读取键现在的值,然后用一条命令去记录键值对,代替之前记录这个键值对的多条命令。

AOF后台重写:

1、服务器进程创建子进程,子进程开始AOF文件重写

2、从创建子进程开始,服务器进程执行的所有写命令不仅要写入AOF缓冲区,

还要写入AOF重写缓冲区写入AOF缓冲区的目的是为了同步到原有的AOF文件。写入AOF重写缓冲区的目的是因为子进程在进行AOF文件重写期间(指子线程将内存数据快照写入临时文件时),服务器进程还在继续处理命令请求,而新的命令可能会对现有的数据库进行修改,从而使得服务器当前的数据库数据和重写后的AOF文件所保存的数据库数据不一致。

3、子进程完成AOF重写工作,向父进程发送一个信号,父进程在接收到该信号后,会执行以下操作:

1.将AOF重写缓冲区中的所有内容写入到新AOF文件中,这样就保证了新AOF文件所保存的数据库数据和服务器当前的数据库数据是一致的。

2.对新的AOF文件进行改名,原子地覆盖现有的AOF文件,完成新旧两个AOF文件的替换。

AOF损坏解决方法

为了解决因为断电或者其他异常原因导致Redis的持久化文件出现异常,利用Redis提供的工具redis-check-aof来检测并自动修复AOF文件并备份异常的AOF文件,并将这个功能在Redis容器的启动时自动执行,这样能保证即使出现异常,平台也能正常工作,运维人员可以离线的修复该异常的AOF文件

8. Redis的管道pipeline

客户端可以一次发送多条命令,不用逐条等待命令的返回值,而是到最后一起读取返回结果

redis使用pipeline完整的交互流程如下:

  1. 客户端进程调用write()把消息写入到操作系统内核为Socket分配的send buffer中
  2. 操作系统会把send buffer中的内容写入网卡,网卡再通过网关路由把内容发送到服务器端的网卡
  3. 服务端网卡会把接收到的消息写入操作系统为Socket分配的recv buffer
  4. 服务器进程调用read()读取消息然后进行处理
  5. 处理完成后调用write()把返回结果写入到服务器端的send buffer
  6. 服务器操作系统再将send buffer中的内容写入网卡,然后发送到客户端
  7. 客户端操作系统将网卡内容读到recv buffer中
  8. 客户端进程调用read()从recv buffer中读取消息并返回

9.如何保证缓存与数据库的双写一致性?

1、先删除缓存,后更新数据库

在更新数据还没提交数据时,一个读请求读取并缓存了旧数据导致数据不一致

解决方案:

延时双删的策略:删除缓存->更新数据库->删除缓存

缓存集群中主从数据复制延时导致的数据不一致问题:

36f7a4029a47f8424a93b7d2917a3985.png

2、先更新数据库,后删除缓存

删除缓存失败导致不一致

解决方案:

使用mq进行缓存删除重试

10、Redis并发竞争key的解决方案

多客户端同时并发写一个key,一个key的值是1,本来按顺序修改为2,3,4,最后是4,但是顺序变成了4,3,2,最后变成了2。

方案:

1、分布式锁

谁先抢到锁谁执行

2、mq队列

将redis的并发操作通过mq实现串行

11、redis位图基本操作

应用场景:

  1. 用户签到
  2. 用户在线状态
  3. 统计活跃用户
  4. 各种状态值
  5. 自定义布隆过滤器
  6. 点赞功能

设置位数组某个下标的值,我们设置bit_user这个key的下标5、7、9为1,指令为SETBIT。

127.0.0.1:6379> SETBIT bit_user 5 1
127.0.0.1:6379> SETBIT bit_user 7 1
127.0.0.1:6379> SETBIT bit_user 9 1

线上实际案例

我们之前做过一个活动叫做21天打卡计划,用户每次进入打卡页都需要展示当前正在进行中的21天打卡具体情况,当前进行到第几天,前面已过的卡点打卡情况,当前21天打卡计划里已经累计打卡了多少次,最开始我们是直接从数据库中取,然后在代码里面去进行统计,之后参与打卡人数逐渐增多,并且这个打卡访问具有极端性,在上午8-10点访问量在某个点会非常高,所以最初的方案已经不可取了。

优化方案:
采用redis的位图实现,每个用户21打卡数据都以位图储存在redis中,用户每次打卡过后都将对应位置为1,例如用户第七天打卡那就使用指令SETBIT bit_user 7 1,那么上述的需求就变得非常简单了。

  1. 查询该用户21天已经累计打过多少次卡直接使用bitcount指令即可得到,无需再去进行数据库查询或者业务代码统计。
  2. 查询前面n天的打卡情况,使用BITFIELD指令得到数值然后在转化为二进制即可。
  3. 如果要展示最近一周的打卡次数,依旧使用BITCOUNT,指令后面跟上下标即可,BITCOUNT bit_user x-7 x,x为当前所在的下标位置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值