Redis常见知识点(面试)

Redis

1. Nosql的概述及作用

  1. Nosql是指非关系性数据库,将数据存储在内存中
  2. 为了满足对数据库高并发读写的需要(高并发);对海量数据的高效率存储和访问的需要(高负载);对数据库的高可扩展性和高可用性的需求
  3. 通常有key-value形式存储的redis、列存储的habse、文档型的mangodb等

2. Redis介绍

  1. Redis是完全开源的、单线程、高性能的、通过C语言实现的key-value数据库
  2. Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用
  3. Redis支持string,list,set,zset,hash等数据结构的存储
  4. Redis支持数据的备份,即master-slave模式的数据备份

3. Redis底层数据结构及数据类型

  1. Redis主要的5种数据类型对应6种底层数据结构,分别是简单动态字符串(SDS),链表,字典(map),跳跃表(skiplist),整数集合(intset),压缩列表(ziplist)
  2. 每种数据类型都有着2种以上的数据结构实现,在不同状态下会进行数据结构的转换
3.1 Redis的zset为什么用跳表而不用红黑树
  1. 跳表实现相比于平衡树更加简单
  2. 在做范围查找时,跳表的效率高于平衡树
  3. 平衡树的插入和删除操作可能引发子树的调整、逻辑复杂,而跳表只需要维护相邻节点即可,效率更高
  4. 查找单个key,跳表和平衡树时间复杂度都是O(logN)

4. Redis的事务

  1. 一次性、顺序性、排他性

  2. redis单条命令保证原子性,但是事务不支持原子性

    原因:异常情况

    ​ 命令有错(编译时异常):事务中所有的命令都不会执行

    ​ 运行时异常:其他命令正常执行,错误命令抛异常 不满足原子性

  3. 事务执行顺序:开启(multi)、命令入队、执行命令(exec)

  4. 用watch命令监控实现乐观锁:事务提交时,如果Key的值已被别的客户端改变,比如某个list已被别的客户端push/pop过了,整个事务队列都不会被执行。通过WATCH命令在事务执行之前监控了多个Keys,倘若在WATCH之后有任何Key的值发生了变化,EXEC命令执行的事务都将被放弃,同时返回Nullmulti-bulk应答以通知调用者事务执行失败

5. Redis的持久化

  1. 概念:Redis的高性能时由于其将所有的数据都存储在了内存中,为了使Redis在宕机或者重启后仍能保证数据不丢失,需要将数据从内存中同步到硬盘中,这一过程就是持久化
5.1 RDB(快照)
  1. 概念:RDB是一种把当前内存中的数据集快照写入磁盘,恢复时将快照文件直接读到内存里的一种默认开启的持久化方式

  2. 生成dump.rdb文件

    1. save命令(默认规则:save 900 1 如果900s内至少有一个key的值发生变化,就进行一次持久化操作)
    2. 执行flushall命令
    3. 退出Redis
  3. 过程原理:Redis单独创建(fork)一个子进程来进行持久化,会先将数据写到一个临时文件中,带持久化过程都结束了,在用这个临时文件替换掉上次持久化好的文件,整个过程,主线程不进行任何IO操作,确保了极高的性能

  4. 优点:

    1. 适合大规模的数据恢复
    2. 对数据完整性要求不高

    缺点:

    1. 需要一定时间间隔(save配置)
    2. fork进程的时候,需要占用一定的内存空间
5.2 AOF(日志)
  1. 概念:以日志的形式记录每一个写操作(读不记录),只允许追加文件,但不可以改写文件,Redis启动之后会主动读取该文件重新构建数据。即Redis重启就根据日志文件的内容将写指令执行一次以完成数据的恢复

  2. 生成appendonly.aof文件
    如果文件出错,Redis无法启动

  3. AOF文件的重写:当AOF文件达到64M(可配置)的时候,Redis就会开辟子进程启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。同时Redis 服务器设置了一个 AOF 重写缓冲区,这个缓冲区是在创建子进程后开始使用,当Redis服务器执行一个写命令之后,就会将这个写命令也发送到 AOF 重写缓冲区。当子进程完成 AOF 重写之后,就会给父进程发送一个信号,父进程接收此信号后,就会调用函数将 AOF 重写缓冲区的内容都写到新的 AOF 文件中

  4. 优点:

    1. 可以通过修改配置(appendfsync)进行不同频率的同步

      always:每一次修改都同步(完整性更高)

      everysec:每秒同步一次,可能丢失一秒的数据

      no:操作系统自己同步,速度最快

    缺点:

    1. 相对于RDB,数据文件更大
    2. AOF运行效率(修复数据)慢

6. Redis消息的发布订阅

  1. 订阅频道:subscribe channel
  2. 发布信息:publish channel message
  3. 原理:通过subscribe命令订阅后,redis-server里维护了一个字典,字典的键就是一个个频道,值就是一个链表。保存了所有订阅了这个频道的客户端。subscribe命令就是将客户端添加到给定的订阅链表中
6.1 Redis发布订阅消息和MQ的区别
redisrabbitmq
可靠性没有相应的机制保证消息的可靠消费,如果发布者发布一条消息,而没有对应的订阅者的话,这条消息将丢失,不会存在内存中具有消息消费确认机制,如果发布一条消息,还没有消费者消费该队列,那么这条消息将一直存放在队列中,直到有消费者消费了该条消息,以此可以保证消息的可靠消费
实时性redis作为高效的缓存服务器,所有数据都存在在服务器中,所以它具有更高的实时性
消费者负载均衡发布订阅模式,一个队列可以被多个消费者同时订阅,当有消息到达时,会将该消息依次发送给每个订阅者队列可以被多个消费者同时监控消费,但是每一条消息只能被消费一次,由于rabbitmq的消费确认机制,因此它能够根据消费者的消费能力而调整它的负载
持久性redis的持久化是针对于整个redis缓存的内容,它有RDB和AOF两种持久化方式(redis持久化方式,后续更新),可以将整个redis实例持久化到磁盘,以此来做数据备份,防止异常情况下导致数据丢失。队列消息都可以选择性持久化,持久化粒度更小,更灵活;
队列监控redis没有所谓的监控平台。rabbitmq实现了后台监控平台,可以在该平台上看到所有创建的队列的详细情况,良好的后台管理平台可以方面我们更好的使用;

7. Redis的主从复制

  1. 为了分担读压力,Redis支持主从复制

  2. 主从复制方式:修改配置/slaveof命令(暂时)

  3. 主从复制类型:全量复制、增量复制

    1. 全量复制:

      1. slave与master建立连接,从节点发送同步命令
      2. master收到命令后,启动一个后台进程,执行bgsave,在后台生成RDB文件,同时master主进程会使用一个缓冲区(复制缓冲区)记录新的写命令并缓存
      3. 主节点的bgsave执行完成后,将RDB文件发送给从节点。从节点首先清除自己的旧数据,然后载入接收的RDB文件(阻塞),将数据库状态更新至主节点执行bgsave时的数据库状态
      4. 主节点将复制缓冲区中的所有写命令发送给从节点,从节点执行这些写命令,将数据库状态更新至主节点的最新状态
      5. 如果从节点开启了AOF,则会触发bgrewriteaof的执行,从而保证AOF文件更新至主节点的最新状态
      补充说明:
      在上述全量复制的流程中,对 master 的性能损耗较大,slave 构建数据的时间也比较长,而且传递 rdb 时还会占用大量带宽,对整个系统的性能和资源的访问影响都比较大。如果master上的磁盘空间有限,那么此时全量同步对于master来说将是一份十分有压力的操作了。可以通过无盘复制来达到目的,由master直接开启一个socket将rdb文件发送给slave服务器。(无盘复制一般应用在磁盘空间有限但是网络状态良好的情况下)
      
    2. 增量复制:

      1. master只发送slave上次复制位置之后的写指令,不用构建 RDB,而且传输内容非常有限,对 master、slave 的负荷影响很小,对带宽的影响可以忽略,整个系统受影响非常小
7.1 Redis主从复制方式的改变
  1. Redis2.8之前主从复制功能缺陷

    在 Redis 中,从服务器对主服务器的复制分为两种情况:

    1. 初次复制:从服务器以前没有复制过主服务器。
    2. 断线后重新复制:从服务器因为网络原因中断复制,但从服务器通过自动重连重新连接上了主服务器,并继续复制主服务器

    对于初次复制来说,旧版复制功能能够很好的完成任务,但对于断线后重新复制来说,旧版复制功能虽然也能让主从服务器数据一致(重新发起SYNC请求,主服务器重新生成RDB文件进行同步),但效率却非常低(可能主从断开连接过程中主服务器只执行了一条写命令却要重新生成整个RDB文件,耗费CPU,再传输给从服务器,耗费网络带宽)。

  2. Redis 2.8 之后复制功能的实现

    为了解决旧版复制功能在处理断线重新复制情况下的低效问题,Redis 从 2.8 版本开始,使用 psync命令代替了 sync 命令来执行复制时的同步操作。

    psync 命令具有完整重同步(full resynchronization)和部分重同步(partial resynchronization)两种模式。

    1. 完整重同步用于处理初次复制情况:完整步骤和 sync 命令的步骤基本一样。
    2. 部分重同步则用于处理断线后重新复制的情况:当从服务器重新连接主服务器时,如果条件允许,主服务器可以将从服务器连接断开期间执行的写命令发送给从服务器,从服务器只要接收并执行这些写命令,就可以将数据库数据更新至和主服务器一样。
7.2 Redis2.8之后主从复制功能的实现
  1. 部分重同步的实现

    • 主服务器的复制偏移量和从服务器的复制偏移量
    • 主服务器的复制积压缓冲区
    • 服务器的运行 ID
  2. 复制偏移量

    执行复制的双方——主服务器和从服务器会分别维护一个复制偏移量

    • 主服务器每次向从服务器传播 N 个字节时,就将自己的复制偏移量 + N
    • 从服务器每次收到主服务器传来的 N 个字节的数据时,就将自己的复制偏移量 + N

    对比主从服务器的复制偏移量可知:

    • 如果主从服务器的复制偏移量相等,则说明主从服务器数据一致
    • 相反,如果主从服务器两者的偏移量不等,则说明主从服务器中的数据不一致
  3. 复制积压缓冲区

    复制积压缓冲区是由主服务器维护的一个固定长度的先进先出(FIFO)队列,默认大小为 1MB

    当主服务器进行命令传播时,不仅会将写命令发送给所有从服务器,还会将写命令入队到复制积压缓冲区里面

    因此,主服务器的复制积压缓冲区里面会保存着一部分最近传播的写命令,并且复制积压缓冲区会为队列中的每个字节记录相应的复制偏移量

    当从服务器重新连上主服务器时,从服务器会通过 PSYNC 命令将自己的复制偏移量(offset) 发送给主服务器,主服务器会根据这个复制偏移量来决定对从服务器执行何种同步操作:

    • 如果 offset 偏移量之后的数据(也即是偏移量 offset + 1 开始的数据)仍然存在于复制积压缓冲区里面,那么主服务器将对从服务器执行部分重同步操作
    • 相反,如果 offset 偏移量之后的数据已经不存在于复制积压缓冲区,那么主服务器将对从服务器执行完整重同步操作

注意:建议根据下述公式调整复制积压缓冲区的大小为:2 * second * write_size_per_second

  • 其中 second 为从服务器断线后重新连接上主服务器所需的平均时间(单位秒)
  • write_size_per_second 是主服务器平均每秒产生的写命令数据量
  • 对应redis-service.conf的配置项repl-backlog-size
  1. 服务器运行ID

    • 每个 Redis 服务器,不论主服务器还是从服务器都有自己的运行 ID
    • 运行 ID 在服务器启动时自动生成,40个随机十六进制字符

    当从服务器对主服务器进行初次复制时,主服务器会将自己的运行 ID 传送给从服务器,而从服务器会将这个运行 ID 保存起来,

    当从服务器断线并重新连上主服务器时,从服务器将向当前连接的主服务器发送之前保存的运行 ID:

    • 如果从服务器保存的运行 ID 和当前连接的主服务器的运行 ID 相同,那么说明从服务器断线之前复制的就是当前连接的这个主服务器,主服务器可以继续尝试执行部分重同步操作
    • 如果从服务器保存的运行 ID 和当前连接的主服务器的运行 ID 不相同,那么说明从服务器断线之前复制的主服务器不是当前连接的这个主服务器,主服务器将对从服务器执行完整重同步操作
7.3 Redis主从复制常见问题
  1. 阻塞问题
    1. 主从复制对于主redis服务器来说是非阻塞的,这意味着当从服务器在进行主从复制同步过程中,主redis仍然可以处理外界的访问请求
    2. 主从复制对于从redis服务器来说也是非阻塞的,这意味着,即使从redis在进行主从复制过程中也可以接受外界的查询请求,只不过这时候从redis返回的是以前老的数据(可配置修改直接返回错误)
    3. 虽然说主从复制过程中对于从redis是非阻塞的,但是当从redis从主redis同步过来最新的数据后还需要将新数据加载到内存中,在加载到内存的过程中是阻塞的,在这段时间内的请求将会被阻塞
  2. https://www.cnblogs.com/kismetv/p/9236731.html#t6

8. Redis哨兵模式

  1. 背景:常见主从复制模型主节点Master 只有一个,一旦主节点挂掉之后,从节点没法担起主节点的任务,那么整个系统也无法运行,为了保证主节点挂掉之后,从节点能自动变成主节点,采用哨兵模式

  2. 原理:哨兵作为独立运行的进程,通过发送命令,等待Redis服务器的响应,从而监控多个运行实例。当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机

  3. 进阶:哨兵模式也存在单点故障问题,如果哨兵机器挂了,那么就无法进行监控了,为此,我们可以使用多个哨兵建立集群进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式

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

    选择新的master节点原则:

    1. 选择 slave-priority(slave节点优先级)最高的slave节点,如果存在则返回,不存在则继续下一步判断
    2. 选择复制偏移量最大的 slave 节点(复制的最完整),如果存在则返回,不存在则继续
    3. 选择runId最小的slave节点(启动最早的节点)

9. Redis集群模式

  1. 数据分区方式:常见的Redis集群架构是三主三从的结构,为了保证数据分片,Redis采用了Hash槽的概念

  2. 为了保证集群中新增节点或者删除节点时,数据迁移量最少,不采用顺序分布、哈希分布,一致性哈希算法诞生

  3. 一致性哈希:一致性Hash是成一个Hash环,按照常用的Hash算法来将对应的key哈希到一个具有2^32次方个桶的空间中,当节点增加或者删除的时候,在环上顺时针找到对应节点,迁移数据

  4. 虚拟槽分区:Redis内部内置了序号 0-16383 个槽位,每个槽位可以用来存储一个数据集合,将这些槽位按顺序分配到集群中的各个节点。每次新的数据到来,会通过哈希函数 CRC16(key) 算出将要存储的槽位下标,然后通过该下标找到前面分配的Redis节点,最后将数据存储到该节点中

10. 缓存穿透、缓存击穿、缓存雪崩

10.1 缓存穿透
  1. 概念:太多请求缓存未命中,直接请求到数据库,数据库压力大

  2. 解决方式:

    1. 布隆过滤器:通过bitmap或Redission实现的一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进性校验,不符合则丢弃,从而避免对底层数据库的查询压力

    2. 缓存空对象:当底层数据库不命中时,即使返回空对象也要将其缓存起来,同时设置合理的过期时间

      存在的问题:

      1. 需要更多空间缓存空值的键
      2. 即使设置了过期时间,还是存在缓存和存储数据有一段时间窗口的不一致,对于需要保持一致性的业务有影响
10.2 缓存击穿
  1. 概念:一个key非常热点,高并发访问,当这个key在失效瞬间,持续的高并发就穿破缓存,直接请求数据库
  2. 解决方式:
    1. 设置热点key用不过期
    2. 定时更新:通过定时任务在某个key即将到达过期时间时重新设置其过期时间
    3. 互斥锁:使用分布式锁。在Redis中根据key获得的value值为空时,先锁上,然后从数据库加载,加载完毕,释放锁。若其他线程也在请求该key时,发现获取锁失败,则睡眠一段时间(比如100ms)后重试
10.3 缓存雪崩
  1. 概念:某一时间段,缓存集中过期失效/Redis宕机
  2. 解决方式:
    1. 设置Rediscover服务高可用(集群)
    2. 限流降级
    3. 数据预热:把可能会大量访问的数据加到缓存中,设置不同的过期时间

11. Redis的过期删除策略以及内存淘汰机制

  1. Redis中有一个maxmemory概念,为了将使用的内存限定在一个固定的大小
11.1 Redis的过期删除策略
  1. 背景:在Redis内部,每当我们设置一个键的过期时间时,Redis就会将该键带上过期时间存放到一个过期字典中。当我们查询一个键时,Redis便首先检查该键是否存在过期字典中,如果存在,那就获取其过期时间。然后将过期时间和当前系统时间进行比对,比系统时间大,那就没有过期;反之判定该键过期

  2. 过期删除策略

    1. 定时删除

    在设置某个key的过期时间同时,我们创建一个定时器,让定时器在该过期时间到来时,立即执行对其进行删除的操作

    优点:定时删除对内存是最友好的,能够保存内存的key一旦过期就能立即从内存中删除

    缺点:对CPU不友好,在过期键比较多的时候,删除过期键会占用一部分 CPU 时间,对服务器的响应时间和吞吐量造成影响

    1. 惰性删除

    设置该key过期时间后,我们不去管它,当需要该key时,我们在检查其是否过期,如果过期,我们就删掉它,反之返回该key

    优点:对 CPU友好,我们只会在使用该键时才会进行过期检查,对于很多用不到的key不用浪费时间进行过期检查

    缺点:对内存不友好,如果一个键已经过期,但是一直没有使用,那么该键就会一直存在内存中,如果数据库中有很多这种使用不到的过期键,这些键便永远不会被删除,内存永远不会释放。从而造成内存泄漏

    1. 定期删除

    Redis默认是每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。

    优点:可以通过限制删除操作执行的时长和频率来减少删除操作对 CPU 的影响。另外定期删除,也能有效释放过期键占用的内存

    缺点:难以确定删除操作执行的时长和频率;如果执行的太频繁,定期删除策略变得和定时删除策略一样,对CPU不友好;如果执行的太少,那又和惰性删除一样了,过期键占用的内存不会及时得到释放;另外最重要的是,在获取某个键时,如果某个键的过期时间已经到了,但是还没执行定期删除,那么就会返回这个键的值,这是业务不能忍受的错误

  3. Redis结合了定期删除和惰性删除,但是如果定期删除漏掉了很多过期key,然后也没及时去查,也就没走惰性删除,大量过期key堆积在内存里,导致redis内存块耗尽 ——使用内存淘汰机制

11.2 Redis的内存淘汰机制
  1. 背景:当现有内存大于 maxmemory 时,便会触发redis主动淘汰内存方式,通过设置 maxmemory-policy,设置不同的内存淘汰机制

  2. 内存淘汰机制

    1. volatile-lru 利用LRU算法(最近最不经常使用 双向链表)移除设置过过期时间的key (LRU:最近使用 Least Recently Used ) 。
    2. allkeys-lru 利用LRU算法移除任何key (和上一个相比,删除的key包括设置过期时间和不设置过期时间的)。通常使用该方式
    3. volatile-random 随机移除设置过过期时间的key 。
    4. allkeys-random 无差别的随机移除。
    5. volatile-ttl 移除即将过期的key(minor TTL)
    6. noeviction 不移除任何key,只是返回一个写错误 ,默认选项,一般不会选用。
  3. 扩展:LFU算法

    1. Redis为了实现近似LRU算法,给每个key增加了一个额外增加了一个24bit的字段,用来存储该key最后一次被访问的时间
    2. LFU将24位拆分成16位时钟+8位计数器
    3. Redis4.0新增内存淘汰机制
      1. volatile-lfu 对有过期时间的key采用LFU淘汰算法
      2. allkeys-lfu 对全部key采用LFU淘汰算法

12. Redis的线程模型

(https://www.jianshu.com/p/8f2fb61097b8)

  1. redis 内部使用文件事件处理器 file event handler,这个文件事件处理器是单线程的,所以 redis 才叫做单线程的模型。它采用 IO 多路复用机制同时监听多个 socket,根据 socket 上的事件来选择对应的事件处理器进行处理。

  2. 文件事件处理器的结构包含 4 个部分

    1. 多个 socket
    2. IO 多路复用程序
    3. 文件事件分派器
    4. 事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)

    多个 socket 可能会并发产生不同的操作,每个操作对应不同的文件事件,但是 IO 多路复用程序会监听多个 socket,会将 socket 产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理

    1. Redis单线程执行,性能高的原因

      1. 基于内存的操作,读写不会受到硬盘I/O速度的限制
      2. Redis采用epoll做为I/O多路复用技术的实现,再加上Redis自身的事件处理模型将epoll中的连接,读写,关闭都转换为了事件,不在I/O上浪费过多的时间
      3. 单线程操作,避免了不必要的上下文切换和和竞争条件,也不存在多进程或者多线程导致的切换而消耗CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗
    2. I/O多路复用

    用户首先将需要进行IO操作的socket添加到select中,然后阻塞等待select系统调用返回。当数据到达时,socket被激活,select函数返回。用户线程正式发起read请求,读取数据并继续执行。这样用户可以注册多个socket,然后不断地调用select读取被激活的socket,redis服务端将这些socket置于队列中,然后,文件事件分派器,依次去队列中取,转发到不同的事件处理器中,提高读取效率

    采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作,从而提高效率

13. Redis和Memcached的区别

  1. redis支持更丰富的数据类型(支持更复杂的应用场景):Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。memcache支持简单的数据类型
  2. Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,而Memecache把数据全部存在内存之中
  3. 集群模式:memcached没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据;但是 redis 目前是原生支持 cluster 模式的
  4. Memcached是多线程,非阻塞IO复用的网络模型;Redis使用单线程的多路 IO 复用模型

img

14. Redis和Mysql数据一致性

  1. 背景:更新Mysql数据后,需要同步redis中缓存的数据

    同步方式:删除缓存,重新从数据库中读取

    如果是更新缓存,存在分布式事务问题,可能出现修改了缓存,数据库修改失败的情况。只是删除缓存的话,就算数据库修改失败,下次查询会直接取数据库的数据,也不会出现脏数据

14.1 延时双删
  1. 为什么要进行延迟双删

    一般我们在更新数据库数据时,需要同步Redis中缓存的数据
    所以存在两种方法:
    (1)第一种方案:先执行update操作,再执行缓存清除
    (2)第二种方案:先执行缓存清除,再执行update操作

    弊端:当存在并发请求时,很容易出现问题
    (1)第一种方案:当请求1执行update操作后,还未来得及进行缓存清除,此时请求2查询到并使用了Redis中的旧数据
    (2)第二种方案:当请求1执行清除缓存后,还未进行update操作,此时请求2进行查询到了旧数据并写入了Redis

    1. 延时双删方式

    在写库前后都进行redis.del(key)操作,并且设定合理的超时时间

    public void write(String key,Object data){
        redis.delKey(key);
        db.updateData(data);
        Thread.sleep(500);
        redis.delKey(key);
    }
    

    具体的步骤就是:

    ​ 先删除缓存;再写数据库;休眠500毫秒(根据业务场景自行确定);再次删除缓存

    休眠目的:

    ​ 确保读请求结束,写请求可以删除读请求造成的缓存脏数据

14.2 基于订阅binlog的异步更新缓存
  1. 当MySql做出修改删除变更时,会在binlog日志中记录。通过使用消息队列对mysql的binlog进行订阅,这样一旦mysql中产生了增删改等操作,我们就可以把binlog相关的消息推送给redis,redis再根据binlog中的记录,对Redis进行更新(类似Mysql的主从备份)
  2. 可以结合使用canal(阿里的一款开源框架),通过该框架可以对MySQL的binlog进行订阅,而canal正是模仿了mysql的slave数据库的备份请求,使得Redis的数据更新达到了相同的效果

15. 其他

  1. Redis大key、大value
  2. Redis解决key冲突(链地址法)
  3. Redis热点key(部署到多台Redis服务器/使用二级缓存存储到jvm)
  4. Redis的rehash
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值