【万字面试题】Redis

文章目录

  • 常见面试题
  • 布隆过滤器
      • 原理和数据结构:
      • 特点和应用场景:
      • 缺点和注意事项:
      • 在python中使用`布隆过滤器`
  • 三种数据`删除策略`
      • LRU (Least Recently Used)
        • 工作原理:
        • 应用场景:
      • LFU (Least Frequently Used)
        • 工作原理:
        • 应用场景:
      • TTL (Time To Live)
        • 工作原理:
        • 应用场景:
      • LRU (Least Recently Used)
      • LFU (Least Frequently Used)
      • TTL (Time To Live)
  • 哈希槽
      • 详细介绍:
      • 使用场景:
  • 分布式锁
      • 工作原理:
      • 特点和注意事项:
      • 使用场景:
  • 缓存穿透
  • 缓存雪崩
  • 缓存击穿
  • 如何保证缓存和数据库的数据一致性

常见面试题

  1. 什么是Redis?

    • Redis是一个开源的内存中数据结构存储,它支持多种数据结构,如字符串、哈希、列表、集合、有序集合等,并提供了持久化、复制、高可用等功能。
  2. Redis的特点是什么?

    • 内存中存储:数据存储在内存中,因此读写速度非常快。
    • 数据结构丰富:支持多种数据结构。
    • 持久化:支持RDB快照和AOF日志两种持久化方式。
    • 高可用:通过主从复制和哨兵或集群实现高可用性。
    • 分布式:支持分片来扩展数据集大小。
  3. Redis支持哪些数据结构?

    • 字符串(String)
    • 哈希(Hash)
    • 列表(List)
    • 集合(Set)
    • 有序集合(Sorted Set)
  4. 什么是Redis的持久化?

    • 持久化是指将数据保存到磁盘上,以便在Redis重启时恢复数据。Redis提供了两种持久化方式:RDB(Redis Database)快照和AOF(Append Only File)日志。
  5. Redis的主从复制是什么?

    • 主从复制是指将一个Redis服务器的数据复制到多个其他Redis服务器,其中一个为主服务器(master),其余为从服务器(slave)。从服务器会持续从主服务器同步数据,以实现数据备份和读取负载均衡。
  6. Redis的集群是什么?

    • Redis集群是多个Redis实例的组合,通过分片的方式存储数据,以提高数据集的大小和吞吐量。
  7. 如何保证Redis的高可用性?

    • 使用主从复制和哨兵机制来监控主服务器的状态并在主服务器宕机时自动切换到备用主服务器。
    • 使用Redis集群来实现数据分片和自动故障转移。
  8. Redis和Memcached有什么区别?

    • Redis支持更多的数据结构(如哈希、列表、集合、有序集合等)而Memcached只支持简单的键值对。
    • Redis支持持久化,而Memcached不支持。
    • Redis支持主从复制和集群,而Memcached不支持。
  9. Redis的数据淘汰策略有哪些?

    • LRU(Least Recently Used):删除最近最少使用的数据。
    • LFU(Least Frequently Used):删除最不经常使用的数据。
    • TTL(Time To Live):设置键的生存时间,过期后自动删除。
  10. 如何使用Redis实现分布式锁?

    • 使用SETNX(SET if Not eXists)命令来设置锁,如果键不存在则设置成功,否则失败。
    • 使用EXPIRE命令为锁设置过期时间,防止锁被长时间占用。
    • 释放锁时使用DEL命令删除键。
  11. Redis的事务支持是怎样的?

    • Redis事务通过MULTI、EXEC、DISCARD和WATCH命令实现,它可以确保一系列命令的原子性执行。
  12. Redis的发布订阅功能是如何工作的?

    • Redis的发布订阅功能允许客户端订阅频道,当有消息发布到频道时,订阅者会收到消息。
  13. 如何使用Lua脚本在Redis中实现原子性操作?

    • Redis通过EVAL命令执行Lua脚本,可以在脚本中实现复杂的原子性操作。
  14. Redis支持哪些客户端?

    • Redis支持多种客户端,包括官方提供的Redis-cli、Jedis(Java)、redis-py(Python)、hiredis(C)等。
  15. Redis的持久化机制对性能有什么影响?

    • RDB持久化机制会在指定的时间间隔生成快照文件,可能会影响Redis的性能。
    • AOF持久化机制会在每个写操作后追加到文件中,可能会影响写入性能。
  16. 如何优化Redis的性能?

    • 使用合适的数据结构。
    • 合理设置缓存失效时间。
    • 使用批量操作。
    • 使用Pipeline减少网络开销。
    • 使用连接池减少连接开销。
  17. Redis集群的工作原理是怎样的?

    • Redis集群通过分片的方式将数据分布到多个节点上,并通过Gossip协议进行节点间通信和数据同步。
  18. Redis的事件驱动模型是怎样的?

    • Redis使用epoll或kqueue等事件驱动模型来处理网络事件,以提高性能和吞吐量。
  19. Redis如何处理并发访问?

    • Redis是单线程的,但通过事件驱动模型和非阻塞IO来处理并发访问,保证了高并发的性能。
  20. 如何在Redis中实现分布式锁的可重入性?

    • 可以使用Redlock算法来实现分布式锁的可重入性,它通过在锁的value中存储锁的持有者和持有次数来实现。
  21. 如何防止Redis的缓存击穿?

    • 可以使用布隆过滤器来过滤不存在的键。
    • 可以设置热门数据的永久有效期,避免热数据过期后频繁重建。
  22. Redis的AOF持久化和RDB持久化的优缺点是什么?

    • AOF持久化提供了更好的数据安全性,但文件体积较大,恢复速度较慢。
    • RDB持久化文件体积较小,恢复速度较快,但可能会丢失最后一次持久化后的数据。
  23. Redis的集群模式下如何进行故障转移?

    • 当主节点故障时,Redis集群会选举一个新的主节点来接替,然后从已有的从节点中选出一个节点作为新的主节点。
  24. Redis的缓存穿透问题如何解决?

    • 可以使用布隆过滤器来过滤无效的请求。
    • 可以设置空值缓存,避免频繁查询不存在的键。
  25. Redis的内存淘汰策略有哪些?

    • LFU(Least Frequently Used):删除最不经常使用的数据。
    • LRU(Least Recently Used):删除最近最少使用的数据。
    • Random(随机淘汰):随机删除数据。
  26. Pipeline 有什么好处,为什么要用 Pipeline?
    可以将多次 IO 往返的时间缩减为一次,前提是 Pipeline 执行的指令之间没有因果相关性。使用 redis-benchmark 进行压测的时候可以发现影响 Redis 的 QPS 峰值的一个重要因素是 Pipeline 批次指令的数目。

  27. MySQL 里有 2000w 数据,Redis 中只存 20w 的数据,如何保证 Redis 中的数据都是热点数据?

Redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。

相关知识:Redis 提供 6 种数据淘汰策略:

volatile-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(驱逐):禁止驱逐数据

文章目录

  • 常见面试题
  • 布隆过滤器
      • 原理和数据结构:
      • 特点和应用场景:
      • 缺点和注意事项:
      • 在python中使用`布隆过滤器`
  • 三种数据`删除策略`
      • LRU (Least Recently Used)
        • 工作原理:
        • 应用场景:
      • LFU (Least Frequently Used)
        • 工作原理:
        • 应用场景:
      • TTL (Time To Live)
        • 工作原理:
        • 应用场景:
      • LRU (Least Recently Used)
      • LFU (Least Frequently Used)
      • TTL (Time To Live)
  • 哈希槽
      • 详细介绍:
      • 使用场景:
  • 分布式锁
      • 工作原理:
      • 特点和注意事项:
      • 使用场景:
  • 缓存穿透
  • 缓存雪崩
  • 缓存击穿
  • 如何保证缓存和数据库的数据一致性

布隆过滤器

布隆过滤器(Bloom Filter)是一种用于快速判断一个元素是否可能存在于一个集合中的数据结构。它的核心思想是通过多个哈希函数将元素映射到一个位数组中,并在查询时检查相应位是否被置位。

原理和数据结构:

  1. 位数组(Bit Array): 布隆过滤器使用一个二进制位数组来表示集合,所有位初始化为0。
  2. 哈希函数(Hash Functions): 布隆过滤器需要多个哈希函数,每个哈希函数可以将输入映射到位数组的不同位置。
  3. 插入操作: 当向布隆过滤器中插入一个元素时,将该元素通过多个哈希函数映射到位数组的相应位置,并将这些位置的位设置为1。
  4. 查询操作: 当查询一个元素是否存在于布隆过滤器中时,将该元素通过相同的哈希函数映射到位数组的相应位置,如果所有位置的位都为1,则可能存在于集合中;如果有任何一个位置的位为0,则该元素一定不存在于集合中。

特点和应用场景:

  1. 空间效率高: 布隆过滤器只需要存储少量的位信息,空间利用率很高。
  2. 查询效率高: 查询一个元素的时间复杂度是常数级别的,与集合大小无关。
  3. 存在误判: 布隆过滤器可能会把不属于集合的元素误判为属于集合(false positive),但不会漏掉实际属于集合的元素。
  4. 应用场景: 布隆过滤器常用于缓存、网络爬虫的URL去重、拦截垃圾邮件等场景,可以有效减少不必要的查询或操作。

缺点和注意事项:

  1. 存在误判: 布隆过滤器可能会误判元素属于集合,因此在一些对准确性要求较高的场景中需要谨慎使用。
  2. 不支持删除操作: 由于删除元素会影响到其他元素的判断结果,布隆过滤器一般不支持删除操作。
  3. 哈希函数选择: 哈希函数的选择对布隆过滤器的性能和误判率有很大影响,需要根据实际情况选择合适的哈希函数。

布隆过滤器是一种简单而有效的数据结构,能够在空间和时间上提供很好的性能,但需要根据具体场景合理使用,并注意其可能存在的误判问题。

在python中使用布隆过滤器

在Python中,你可以使用第三方库pybloom_live来实现布隆过滤器。下面是一个简单的示例,演示如何在Python 3中使用布隆过滤器:

首先,你需要安装pybloom_live库。你可以通过以下命令使用pip进行安装:

pip install pybloom-live

接下来,你可以使用以下示例代码来创建并使用布隆过滤器:

from pybloom_live import BloomFilter

# 创建一个布隆过滤器,设置预期容量为10000,期望误差率为0.001
bf = BloomFilter(capacity=10000, error_rate=0.001)

# 添加元素到布隆过滤器
bf.add("apple")
bf.add("banana")
bf.add("orange")

# 检查元素是否存在于布隆过滤器中
print("apple" in bf)  # 输出 True
print("grape" in bf)  # 输出 False,可能是误判

# 布隆过滤器不支持删除操作

# 保存布隆过滤器到文件
with open("bloom_filter.bf", "wb") as f:
    bf.tofile(f)

# 从文件中加载布隆过滤器
with open("bloom_filter.bf", "rb") as f:
    bf_loaded = BloomFilter.fromfile(f)

# 检查加载后的布隆过滤器是否包含元素
print("apple" in bf_loaded)  # 输出 True
print("grape" in bf_loaded)  # 输出 False,可能是误判

在上面的示例中,我们首先创建了一个布隆过滤器,并向其中添加了一些元素。然后,我们检查了某些元素是否存在于布隆过滤器中。最后,我们将布隆过滤器保存到文件,并从文件中加载了一个新的布隆过滤器,并再次检查了元素的存在性。

请注意,布隆过滤器可能会产生误判,因此在实际应用中,你需要根据具体情况选择合适的预期容量和误差率来平衡存储空间和误判率。


文章目录

  • 常见面试题
  • 布隆过滤器
      • 原理和数据结构:
      • 特点和应用场景:
      • 缺点和注意事项:
      • 在python中使用`布隆过滤器`
  • 三种数据`删除策略`
      • LRU (Least Recently Used)
        • 工作原理:
        • 应用场景:
      • LFU (Least Frequently Used)
        • 工作原理:
        • 应用场景:
      • TTL (Time To Live)
        • 工作原理:
        • 应用场景:
      • LRU (Least Recently Used)
      • LFU (Least Frequently Used)
      • TTL (Time To Live)
  • 哈希槽
      • 详细介绍:
      • 使用场景:
  • 分布式锁
      • 工作原理:
      • 特点和注意事项:
      • 使用场景:
  • 缓存穿透
  • 缓存雪崩
  • 缓存击穿
  • 如何保证缓存和数据库的数据一致性

三种数据删除策略

当我们需要管理缓存或者存储一些临时数据时,常常需要一些策略来决定何时删除数据。LRU、LFU 和 TTL 是三种常见的数据删除策略,它们各自适用于不同的场景,下面我会详细介绍它们的工作原理和应用场景。

LRU (Least Recently Used)

LRU(最近最少使用)是一种缓存淘汰算法,其核心思想是基于时间局部性原理,即最近被访问过的数据在未来也有可能被再次访问。LRU 算法认为,最近使用过的数据可能在未来会被再次使用,因此当缓存空间不足时,应该优先淘汰最久未被使用的数据。

工作原理:
  1. 当一个数据被访问时,LRU 算法会将这个数据移到队列的头部(或者说置于队列的最近位置)。
  2. 当缓存空间不足时,LRU 算法会淘汰队列尾部(或者说队列最久未被访问的)的数据。
应用场景:
  1. Web 缓存:缓存网页、图片等资源,以加快用户访问速度。
  2. 数据库缓存:缓存查询结果,以减少数据库访问次数。
  3. 页面置换算法:操作系统中,当内存不足时,用于选择合适的页面进行置换。

LFU (Least Frequently Used)

LFU(最不经常使用)是一种缓存淘汰算法,其核心思想是基于访问局部性原理,即经常被访问的数据在未来仍然有可能频繁被访问。LFU 算法认为,被访问次数较少的数据可能是不常用的数据,因此当缓存空间不足时,应该优先淘汰访问次数较少的数据。

工作原理:
  1. 当一个数据被访问时,LFU 算法会增加该数据的访问计数。
  2. 当缓存空间不足时,LFU 算法会淘汰访问计数最低的数据。
应用场景:
  1. 缓存系统:适用于需要根据数据的使用频率来进行淘汰的场景,如热点数据缓存。
  2. 数据库管理:可以用于缓存数据库查询结果,根据查询的频率来进行数据淘汰。

TTL (Time To Live)

TTL(生存时间)是一种设置键的生存时间的机制,常用于缓存系统中。当键的生存时间超过指定的时间后,键会被自动删除。

工作原理:
  1. 当设置一个键的 TTL 后,系统会记录键的创建时间。
  2. 当访问这个键时,系统会检查当前时间与键的创建时间之间的时间差是否超过 TTL。
  3. 如果超过 TTL,则系统会自动删除该键。
应用场景:
  1. 缓存系统:可以根据数据的更新频率来设置 TTL,保证缓存数据的时效性。
  2. 会话管理:在 Web 开发中,可以使用 TTL 来设置用户会话的有效期,保证安全性。

总的来说,LRU、LFU 和 TTL 是常用的缓存淘汰策略,根据具体的场景和需求选择合适的策略可以有效提高缓存系统的效率和性能。

设置 LRU、LFU 和 TTL 通常需要根据具体的缓存系统或应用程序来进行配置。下面我将简要介绍如何设置这三种策略:

LRU (Least Recently Used)

  1. 基于数据结构的实现:在使用数据结构实现缓存时,可以利用双向链表和哈希表结合的方式来实现LRU。在每次访问缓存数据时,将该数据移到链表的头部。当缓存空间不足时,淘汰链表尾部的数据。

  2. 缓存框架的配置:如果使用的是一些成熟的缓存框架,如Redis、Memcached等,通常会提供配置选项来设置LRU淘汰策略。在Redis中,可以通过配置maxmemory-policy选项为"volatile-lru"或"allkeys-lru"来启用LRU淘汰策略。

LFU (Least Frequently Used)

  1. 基于数据结构的实现:LFU通常使用哈希表和最小堆来实现。哈希表用于存储键值对,最小堆用于按照访问频率维护数据。当一个数据被访问时,更新其在最小堆中的访问频率,以便在淘汰时能够找到访问频率最低的数据。

  2. 缓存框架的配置:与LRU类似,一些缓存框架提供了配置选项来启用LFU淘汰策略。在Redis中,可以通过配置maxmemory-policy选项为"volatile-lfu"或"allkeys-lfu"来启用LFU淘汰策略。

TTL (Time To Live)

  1. 设置缓存数据的生存时间:在存储数据时,设置每个键的生存时间。在Redis中,可以使用SET命令的EXPIRE选项或者SETEX命令来设置键的生存时间。

  2. 定期清理过期数据:定期检查缓存中的数据,将已经过期的数据进行清理。在Redis中,可以使用定时任务或者使用Redis自带的过期键删除机制来清理过期数据。

以上是一些常见的设置方法,具体实现方式会根据具体的缓存系统或应用程序而有所不同。在配置时,还需要考虑到系统的性能和实际需求,选择合适的策略和参数。

文章目录

  • 常见面试题
  • 布隆过滤器
      • 原理和数据结构:
      • 特点和应用场景:
      • 缺点和注意事项:
      • 在python中使用`布隆过滤器`
  • 三种数据`删除策略`
      • LRU (Least Recently Used)
        • 工作原理:
        • 应用场景:
      • LFU (Least Frequently Used)
        • 工作原理:
        • 应用场景:
      • TTL (Time To Live)
        • 工作原理:
        • 应用场景:
      • LRU (Least Recently Used)
      • LFU (Least Frequently Used)
      • TTL (Time To Live)
  • 哈希槽
      • 详细介绍:
      • 使用场景:
  • 分布式锁
      • 工作原理:
      • 特点和注意事项:
      • 使用场景:
  • 缓存穿透
  • 缓存雪崩
  • 缓存击穿
  • 如何保证缓存和数据库的数据一致性

哈希槽

Redis 哈希槽(Redis Cluster Slot)是在 Redis 集群中用于分片的一种机制。Redis 集群通过哈希槽将数据分散存储在多个节点上,实现了水平扩展和负载均衡。

详细介绍:

  1. 哈希槽的概念

    • Redis 将整个数据集分成 16384 个哈希槽,每个槽都有一个唯一的编号,从 0 到 16383。
    • 每个键都会被哈希到一个特定的槽上,根据键计算得出的哈希值被取模 16384 后所得到的值就是对应的槽号。
  2. 数据分片

    • 在 Redis 集群中,每个节点负责管理一部分哈希槽。每个节点都知道自己负责的哈希槽范围。
    • 当执行写操作时,客户端会计算键的哈希值,并根据哈希槽范围将数据发送到相应的节点上。
    • 通过将数据分散存储在多个节点上,实现了数据的分布式存储和负载均衡。
  3. 哈希槽的迁移

    • 当 Redis 集群中的节点数量发生变化或者某个节点负载过高时,会触发哈希槽的迁移。
    • 哈希槽迁移过程中,会将槽上的数据从源节点迁移到目标节点,确保数据的平衡分布。
    • 在迁移过程中,集群仍然可以对外提供读写服务,不会中断客户端的访问。
  4. 哈希槽的管理

    • Redis 集群提供了命令和 API 来管理哈希槽,包括手动设置槽的范围、获取节点的槽分布情况、触发槽的迁移等操作。
    • 通过这些管理工具,管理员可以灵活地管理集群的数据分布,以满足不同的需求。

使用场景:

  • 水平扩展:通过将数据分散存储在多个节点上,实现了数据的水平扩展,可以处理更大规模的数据量和请求。
  • 负载均衡:哈希槽的分布式存储机制使得集群中的数据负载得以均衡,提高了系统的整体性能和可用性。
  • 数据迁移:当集群中的节点发生变化或者负载不均时,可以通过哈希槽的迁移来重新平衡数据,保持集群的稳定运行。

总的来说,Redis 哈希槽是 Redis 集群中实现数据分片和负载均衡的关键机制,通过合理管理哈希槽,可以实现高效稳定的分布式存储服务。

分布式锁

Redis 分布式锁是在 Redis 数据库中利用原子操作和特定的数据结构来实现的一种分布式锁机制,用于解决分布式系统中多个客户端对共享资源的并发访问问题。下面是详细介绍:

工作原理:

  1. 获取锁

    • 客户端通过执行一段原子操作(通常是 SETNX 命令)来尝试获取锁,如果锁的键不存在,则设置锁的键,并设置一个过期时间,以防止锁忘记释放导致死锁。
    • 如果获取锁成功,则表示该客户端获得了对共享资源的独占访问权;如果获取失败,则表示锁已经被其他客户端持有。
  2. 释放锁

    • 当客户端使用完共享资源后,需要执行释放锁的操作。客户端通过删除锁的键来释放锁。
    • 释放锁时,需要确保释放的是自己持有的锁,以防止误释放其他客户端持有的锁。
  3. 锁的续约

    • 在某些情况下,客户端可能需要持有锁的时间比较长,但是锁的过期时间可能较短,这时客户端可以通过重设过期时间的方式来实现锁的续约,保证自己持有锁的时间不会过期。

特点和注意事项:

  • 互斥性:Redis 分布式锁能够保证在任意时刻只有一个客户端持有锁,确保了对共享资源的互斥访问。
  • 可重入性:同一个客户端在持有锁期间可以多次获取同一把锁,即可重入。
  • 阻塞和非阻塞模式:获取锁的操作可以是阻塞的(即客户端一直等待直到获取到锁)或者是非阻塞的(即尝试获取一次后立即返回结果)。
  • 锁的超时和续约:锁可以设置过期时间,在获取锁后需要及时释放,避免出现死锁情况;同时可以通过续约操作来延长锁的持有时间。
  • 误删问题:在释放锁时,需要确保删除的是自己持有的锁,防止误删其他客户端持有的锁。
  • 性能影响:使用 Redis 分布式锁可能会对 Redis 服务器的性能产生一定影响,特别是在高并发的情况下,需要注意锁的使用方式和频率,以避免对系统性能造成过大的影响。

使用场景:

  • 分布式系统中对共享资源的并发访问控制。
  • 实现任务队列的消费者竞争模式。
  • 数据库操作的乐观锁机制。

总的来说,Redis 分布式锁是一种简单有效的分布式锁实现方式,通过合理地使用和管理,可以解决分布式系统中的并发访问问题。


缓存穿透

缓存穿透说简单点就是大量请求的 key 根本不存在于缓存中,导致请求直接到了数据库上,根本没有经过缓存这一层。比如某个攻击者故意制造我们缓存中不存在的 key 发起大量请求,导致大量请求落到数据库上,使得数据库由于性能的原因崩溃,导致系统异常

缓存穿透问题产生
在这里插入图片描述

使用布隆过滤器
布隆过滤器是一个非常神奇的数据结构,通过它我们可以非常方便地判断一个给定数据是否存在于海量数据中

具体是这样做的:把所有可能存在的请求的值都存放在布隆过滤器中,当用户请求过来,先判断用户发来的请求的值是否存在于布隆过滤器中。不存在的话,直接返回请求参数错误信息给客户端,存在的话才会走下面的流程
在这里插入图片描述

缓存雪崩

缓存雪崩描述的就是这样一个简单的场景:缓存在同一时间大面积的失效,后面的请求都直接落到了数据库上,造成数据库短时间内承受大量请求

在这里插入图片描述

解决办法
针对 Redis 服务不可用的情况:

采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用限流,避免同时处理大量的请求

针对热点缓存失效的情况:

  • 设置不同的失效时间比如随机设置缓存的失效时间
  • 缓存永不失效

缓存击穿

如果缓存中的某个热点数据过期了,此时大量的请求访问了该热点数据,就无法从缓存中读取,直接访问数据库,数据库很容易就被高并发的请求冲垮,这就是缓存击穿的问题

击穿其实可以看做是雪崩的一个子集,解决方法一般有两种,设置热点数据永不过期和设置互斥锁

所谓的互斥锁,就是保证同一时间只有一个业务线程更新缓存,对于没有获取互斥锁的请求,要么等待锁释放后重新读取缓存,要么就返回空值或者默认值

在这里插入图片描述

如何保证缓存和数据库的数据一致性

其实这是一个非常庞大且复杂的问题,根本不是一两句话能够说清楚的,如果要完全规避一致性问题,那么整个系统也会变得非常复杂

一般来说可以进行如下处理:更新 DB,然后删除 cache

当然此时有可能遇到更新 DB 成功,但是删除 cache 失败的情况,处理办法大致有两种:

缓存失效时间变短(不推荐,治标不治本) :我们让缓存数据的过期时间变短,这样的话缓存就会从数据库中加载数据。另外,这种解决办法对于先操作缓存后操作数据库的场景不适用
增加 cache 更新重试机制(常用):如果 cache 服务当前不可用导致缓存删除失败的话,我们就隔一段时间进行重试,重试次数可以自己定。如果多次重试还是失败的话,我们可以把当前更新失败的 key 存入队列中,等缓存服务可用之后,再将缓存中对应的 key 删除即可

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/627173.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vs2019 c++中模板 enable_if_t 的使用

&#xff08;1&#xff09; 该模板的定义如下&#xff1a; template <bool _Test, class _Ty void> struct enable_if {}; // no member "type" when !_Testtemplate <class _Ty> struct enable_if<true, _Ty> { // type is _Ty for _Testusing …

OSEK应用模式

1 前言 应用模式&#xff08;Application modes)用于区分不同的场景&#xff0c;以便在系统运行时&#xff0c;组织各自相互独立的OS相关的资源集合&#xff0c;是一种分而治之的思想体现。不同的应用模式是互斥的&#xff0c;即系统当前必须在一种应用模式&#xff08;且只能在…

OV SSL证书的特点

OV SSL证书&#xff0c;全称为Organization Validation SSL Certificate&#xff08;组织验证型SSL证书&#xff09;&#xff0c;是一种中级的SSL证书类型。与仅验证域名所有权的DV&#xff08;Domain Validation&#xff09;证书不同&#xff0c;OV证书在颁发前会执行更加严格…

01.认识HTML及常用标签

目录 URL&#xff08;统一资源定位系统&#xff09; HTML&#xff08;超文本标记语言&#xff09; 1&#xff09;html标签 2&#xff09;head标签 3&#xff09;title标签 4&#xff09;body标签 标签的分类 DTD文档声明 基础标签 1&#xff09;H系列标签 2&#xff09…

C++基础与深度解析 | 语句 | 分支语句 | 循环语句 | 达夫设备

文章目录 一、语句基础二、分支语句1.分支语句--if2.分支语句--switch 三、循环语句1.循环语句--while2.循环语句--do-while3.循环语句--for4.循环语句--基于范围的for循环5.break / continue语句四、语句的综合应用--达夫设备 一、语句基础 语句的常见类别&#xff1a; 表达…

如何在 Ubuntu 12.10 上使用 Python 创建 Nagios 插件

介绍 Python 是一种在 Linux 上默认可用的流行命令处理器。 我们之前已经介绍过如何在 Ubuntu 12.10 x64 上安装 Nagios 监控服务器。 这一次&#xff0c;我们将扩展这个想法&#xff0c;使用 Python 创建 Nagios 插件。 这些插件将在客户 VPS 上运行&#xff0c;并通过 NR…

树莓派|角速度和加速度传感器

角速度传感器和加速度传感器是常见的惯性传感器&#xff0c;常用于测量物体的旋转和线性运动。 角速度传感器&#xff08;Gyroscope&#xff09;用于测量物体绕三个轴&#xff08;X、Y、Z&#xff09;的旋转速度或角速度。它可以提供关于物体在空间中的旋转方向和角度变化的信…

数据结构学习/复习14--归并排序的递归与循环实现/计数排序

一、归并排序 1.递归实现 注意事项&#xff1a;即使排序的数字个数不为2的倍数也可正常分解&#xff0c;其思想没有规定一定要左右数目对称才可合并 注意事项&#xff1a;归并的思想还适用于外排序 2.递归改循环 注意事项&#xff1a;边界处理与非2的n次方倍的处理 版本1&…

win10下,svn上传.so文件失败

问题&#xff1a;win10下使用TortoiseSVN&#xff0c;svn上传.so文件失败 解决&#xff1a;右键&#xff0c;选择Settings&#xff0c;Global ignore pattern中删除*.so&#xff0c;保存即可。

网络3--网络通信的深度理解(端口号)

网络通信的进一步理解 两个主机间进行通信&#xff0c;其实是两个主机间的软件进行通信&#xff0c;软件也就是可执行程序&#xff0c;运行时就是进程&#xff0c;所以也为进程间通信。 进程间通信需要共享资源&#xff0c;这里两个主机间的共享资源是网络&#xff0c;利用的是…

指针(4)

1. 字符指针变量 在指针的类型中我们知道有⼀种指针类型为字符指针 char* ; 一般使用: int main() {char i a;char* p &i;*p q;printf("%c", i);return 0; } 然后我们看这个例子,这是把⼀个字符串放到pstr指针变量里了吗&#xff1f; 事实上不是,他只是将…

如何管理多个版本的Node.js

我们如何在本地管理多个版本的Node.js&#xff0c;有没有那种不需要重新安装软件再修改配置文件和环境变量的方法&#xff1f;经过我的查找&#xff0c;还真有这种方式&#xff0c;那就是nvm&#xff08;Node Version Manager&#xff09;。 下面我就给大家介绍下NVM的使用 1…

笔记本黑屏,重新开机主板没有正常运作的解决办法

拆开笔记本后壳&#xff0c;打开看到主板&#xff0c;将主板上的这颗纽扣电池拆下来&#xff0c;如果是带连接线的&#xff08;如下图&#xff09;&#xff0c;可以将接口处线头拔出&#xff0c;等1分钟再把线接上。 ------------- 以下是科普 首先&#xff0c;电脑主板上的这…

Llama-Factory + Ollama 打造属于自己的中文版 Llama3

Meta 推出 Llama3 也有一小段时间了。Llama3 包含 8B 和 70B 两种参数规模&#xff0c;涵盖预训练和指令调优的变体。Llama 3 支持多种商业和研究用途&#xff0c;并已在多个行业标准测试中展示了其卓越的性能&#xff08;关于Llama3的具体介绍可以参考本站另外一篇博文&#x…

详解xlsxwriter 操作Excel的常用API

我们知道可以通过pandas 对excel 中的数据进行处理分析&#xff0c;但是pandas本身对格式化数据方面提供了很少的支持&#xff0c;如果我们想对pandas进行数据分析后的数据进行格式化相关操作&#xff0c;我们可以使用xlsxwriter&#xff0c;本文就对xlsxwriter的常见excel格式…

Java聚合项目打包运行笔记

聚合项目创建 略 聚合项目打包配置 父工程 pom文件添加 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>…

【18-Ⅰ】Head First Java 学习笔记

HeadFirst Java 本人有C语言基础&#xff0c;通过阅读Java廖雪峰网站&#xff0c;简单速成了java&#xff0c;但对其中一些入门概念有所疏漏&#xff0c;阅读本书以弥补。 第一章 Java入门 第二章 面向对象 第三章 变量 第四章 方法操作实例变量 第五章 程序实战 第六章 Java…

ROS2+TurtleBot3+Cartographer+Nav2实现slam建图和导航

0 引言 入门机器人最常见的应用就是slam建图和导航&#xff0c;本文将详细介绍这一流程&#xff0c; 便于初学这快速上手。 首先对需要用到的软件包就行简单介绍。 turtlebot3: 是一个小型的&#xff0c;基于ros的移动机器人。 学习机器人的很多示例程序都是基于turtlebot3。 …

Java入门之数据类型和变量

1.字面常量 字面常量就是在程序运行中&#xff0c;固定不变的量&#xff0c;例如如下的代码 public class Demo{public static void main(String[] args){System.Out.println("hello world!");System.Out.println(100);System.Out.println(3.14);System.Out.println…

Windows Docker 部署 Etcd 键值存储系统

一、简介 etcd 是一个由 CoreOS 团队发起的开源项目&#xff0c;它用 Go 语言实现&#xff0c;是一个分布式、高可用的键值存储系统。etcd 采用 Raft 算法&#xff0c;确保了数据的强一致性和高可用性&#xff0c;即使集群中有部分节点发生故障&#xff0c;也能保持服务的正常…