redis面试题
Redis用murmurHash2做字符串的哈希函数
-
redis的对象类型有哪些?底层数据结构是怎么设计的?
Redis存储的K-V数据是以哈希表来实现的,key固定为字符串,value可以是哈希、链表、数组等各种数据结构
1.string
是redis中key的类型,底层用SDS简单动态字符串实现,可以存储任何类型的数据(使用原因), -
解决了c语言字符串的数组越界问题(例如字符串拼接)(添加长度size字段解决,空间不足自动扩容)
-
支持二进制数据的存储,通过长度字段获取字符串的大小,所以不需要用c语言的\0做分隔符,也就支持存储二进制数据
2.list
底层用双向链表实现
3.hash
1.普通的hash表,使用链式哈希解决哈希冲突
2.渐进式rehash,元素数量=bucket数量时(即负载因子=1)认为即将发生哈希冲突,需要对bucket扩容并重新映射:
为了避免 rehash 在数据迁移过程中,因拷⻉数据的耗时,影响 Redis 性能的情况,所以 Redis 采⽤了渐 进式 rehash,也就是将数据的迁移的⼯作不再是⼀次性迁移完成,⽽是分多次迁移。当 hashtable 中的元素过多的时候,不能一次性 rehash 到 ht[1];这样会长期占用 redis,其他命令得不到响应;所以需 要使用渐进式 rehash;
渐进式 rehash 步骤如下: 给「哈希表 2」 分配空间; 在 rehash 进⾏期间,每次哈希表元素进⾏新增、删除、查找或者更新操作时,Redis 除了会执⾏对 应的操作之外,还会顺序将「哈希表 1 」中索引位置上的所有 key-value 迁移到「哈希表 2」 上; 随着处理客户端发起的哈希表操作请求数量越多,最终在某个时间点,会把「哈希表 1 」的所有 key-value 迁移到「哈希表 2」,从⽽完成 rehash 操作。
在进⾏渐进式 rehash 的过程中,会有两个哈希表,所以在渐进式 rehash 进⾏期间,哈希表元素的删除、 查找、更新等操作都会在这两个哈希表进⾏。 ⽐如,查找⼀个 key 的值的话,先会在「哈希表 1」 ⾥⾯进⾏查找,如果没找到,就会继续到哈希表 2 ⾥ ⾯进⾏找到。 另外,在渐进式 rehash 进⾏期间,新增⼀个 key-value 时,会被保存到「哈希表 2 」⾥⾯,⽽「哈希表 1」 则不再进⾏任何添加操作,这样保证了「哈希表 1 」的 key-value 数量只会减少,随着 rehash 操作的 完成,最终「哈希表 1 」就会变成空表。
4.set
整数数组实现,zset用跳表实现,以支持范围查询 -
基于redis实现限流有哪些方式?
基于 Redis 实现限流通常利用其高效的原子性操作和持久化存储能力。限流的目的是控制请求频率,防止系统过载或避免滥用。以下是几种常见的限流方式:
1. 计数器法(固定窗口限流)
原理:设定一个时间窗口(如 1 秒钟或 1 分钟),在该窗口内计数请求次数,如果超过设定的阈值则限制访问。
实现:
- 使用
INCR
命令对某个键的计数器进行自增。 - 使用
EXPIRE
命令为该计数器设置过期时间,例如每分钟清零。 - 每次请求时,先判断计数器是否超出限制,超出则拒绝请求。
优缺点:
- 优点:简单易实现,计数器不会在短时间内飙升。
- 缺点:边界问题明显,如果恰好在窗口边界请求数大,可能导致瞬时突增(例如窗口重置的瞬间有大量请求涌入)。
2. 滑动窗口限流
原理:滑动窗口限流通过细分时间窗口来缓解固定窗口的边界问题,将大窗口细分成多个小时间片段,从而更精确地限制请求频率。
实现:
- 在 Redis 中存储每个时间片段的计数。
- 每次请求时,首先移除过期的时间片段,统计当前时间窗口的请求总数。
- 如果总数超过限制,则拒绝请求,否则允许。
优缺点:
- 优点:能够更平滑地控制请求数,减少突发流量的冲击。
- 缺点:实现稍微复杂,存储开销比固定窗口稍高。
3. 漏桶算法(Leaky Bucket)
原理:请求进入一个漏桶中,桶中的水滴(请求)以固定速率漏出,超过桶容量的请求被丢弃。适用于场景:限制流量速率,允许短时间内的突发流量。
实现:
- 在 Redis 中维护一个请求队列或计数器。
- 定时任务以固定速率从漏桶中移除请求计数。
- 新请求到来时,如果桶未满,则允许通过;如果桶满则丢弃。
优缺点:
- 优点:能平滑处理请求,严格控制流量输出速率。
- 缺点:实现复杂,可能需要依赖 Redis 的 Lua 脚本实现精确控制。
4. 令牌桶算法(Token Bucket)
原理:令牌桶以固定速率向桶中加入令牌,每次请求需要消耗一个令牌,没有令牌则拒绝访问。适合流量峰值控制。
实现:
- 在 Redis 中存储令牌桶的当前令牌数以及上次添加令牌的时间。
- 每次请求时,首先根据当前时间判断应添加的令牌数量,更新桶的令牌数。
- 检查桶中是否有足够的令牌,若有则允许请求并减少令牌数,否则拒绝。
优缺点:
- 优点:允许短时间内的突发请求,同时控制总体流量。
- 缺点:实现稍复杂,可能需 Lua 脚本控制并发,避免 Race Condition。
5. Redis Cell(令牌桶+滑动窗口)
原理:Redis 4.0 引入了 CL.THROTTLE
命令来简化限流。Redis Cell 模块结合了滑动窗口和令牌桶算法,可直接实现限流。
实现:
- 通过
CL.THROTTLE
来设定速率、桶容量等参数。 - 每次请求调用
CL.THROTTLE
,根据返回值判断请求是否允许。
优缺点:
- 优点:实现简单,性能较高,无需手写 Lua 脚本。
- 缺点:Redis Cell 是 Redis Module,需单独安装。
总结
- 固定窗口适用于简单限流场景。
- 滑动窗口和令牌桶适合处理突发流量。
- 漏桶严格控制流量速率,适合实时性要求高的场景。
- Redis Cell最简便,但需 Redis 支持该模块。
选择限流方式需根据业务场景权衡,请求频率、瞬时流量、以及实现复杂度都是考虑因素。
- Redis为什么是单线程?这里单线程指什么?
Redis 的“单线程”指的是它的主要网络请求处理和数据操作都是通过一个单线程执行的,通常称之为“主线程”。该线程负责处理客户端请求、数据读写、键过期等主要任务。
1. Redis 为什么选择单线程
Redis 选择单线程的主要原因是为了简单高效地提供高性能服务:
-
CPU 并不是瓶颈:Redis 的瓶颈通常在于内存和网络 IO,而不是 CPU。大部分操作(如字符串、列表等基本数据类型的操作)在内存中执行,速度非常快,因此单线程足以应对大量请求。
-
避免多线程带来的锁开销:多线程编程需要考虑资源共享问题,为了保持数据一致性,通常需要加锁。锁会带来一定的开销和复杂性,尤其在高并发环境下,会增加性能损耗和程序复杂度。单线程模式消除了锁竞争问题,保证了操作的原子性和一致性。
-
事件驱动模型:Redis 采用基于 IO 多路复用的事件驱动机制处理请求,在单线程中通过
epoll
、select
等 IO 多路复用技术处理多个客户端连接,避免了线程切换和资源竞争,实现了高效的并发处理。
2. Redis 单线程的实际运行方式
Redis 实际上是单线程执行主要的数据库操作,而并非整个程序都是单线程。Redis 内部使用了多线程来处理一些特定任务,例如:
-
持久化:在 RDB 快照和 AOF 文件重写过程中,Redis 使用了后台线程来执行磁盘 IO 操作,以避免影响主线程处理请求。
-
异步删除和压缩:对于一些大键值(如大列表、哈希表等)的删除操作,Redis 会在后台异步执行,避免主线程阻塞。
-
复制和集群通信:在主从复制和集群模式下,Redis 使用额外线程处理复制和集群间通信任务。
3. 单线程与性能优化
尽管 Redis 主线程是单线程,但其性能依然足够高。在 CPU 不是主要瓶颈的情况下,Redis 能够利用其高效的内存操作和网络 IO 多路复用,保持高吞吐量。单线程模式让 Redis 更加简单直接,同时也有助于减少潜在的并发错误,提升了系统的稳定性。
不过,为了在多核 CPU 上获得更好性能,Redis 6.0 引入了多线程用于处理网络 IO,但数据操作仍然在主线程中完成。
- Redis如何实现分布式锁?有哪些缺陷?
Redis 实现分布式锁主要依靠SETNX
(Set if Not Exists)和EXPIRE
(设置键过期时间)来实现,也可以使用SET
命令的扩展形式。常用的方式有简单分布式锁和更为复杂的 Redlock 算法。
1. Redis 分布式锁的实现原理
简单分布式锁
一个简单的分布式锁通常实现如下:
-
获取锁:使用
SET resource_name unique_id NX PX 30000
命令,其中:resource_name
是锁的名称。unique_id
是唯一标识,用于区分谁持有锁。NX
保证只有在resource_name
不存在时才会创建该键。PX 30000
设置锁的自动过期时间(如 30 秒),以避免因为客户端崩溃导致锁无法释放。
-
释放锁:在释放锁时,首先判断锁是否是自己持有的(通过
unique_id
验证),如果是,则删除键。通常通过 Lua 脚本保证原子性:if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("DEL", KEYS[1]) else return 0 end
2. Redis 分布式锁的缺陷
Redis 实现分布式锁虽然简单,但也存在以下缺陷:
-
锁的自动过期问题:如果持有锁的任务未能在过期时间内完成,锁将自动失效,导致其他客户端可以获取该锁。此时,可能会导致并发问题。
-
时钟偏差:Redlock 假设不同服务器之间的时钟偏差可控,但在实际网络环境中,不同机器间的时钟可能并不完全同步,可能导致锁的可靠性降低。
-
网络分区问题:在网络分区的情况下,Redlock 可能会出现多个节点持有同一锁的情况,导致数据不一致风险。
-
锁释放的可靠性:简单分布式锁使用
DEL
释放锁,如果客户端在操作前崩溃,锁可能无法正确释放。而 Redlock 通过在多数实例上加锁来增加可靠性,但也增加了实现复杂性和网络开销。
3. Redis 分布式锁的改进建议
为缓解以上缺陷,可以采用一些优化方法:
-
续租机制:对锁的持有者提供续租的功能,确保锁在任务未完成时不会因超时而释放。
-
锁竞争检测:使用随机等待或指数退避机制,减少并发时获取锁的激烈竞争。
-
更严格的时钟同步:尽可能减少各个 Redis 实例之间的时钟偏差,以减少因时钟偏移带来的锁误释放或重复持有问题。
-
Redis如何做到高可用?
Redis 实现高可用性主要依赖于主从复制(Replication)、哨兵模式(Sentinel)和 Redis Cluster 分布式集群架构。每种方式在 Redis 的可用性保障方面起到了不同的作用。 -
主从复制(Replication)
Redis 的主从复制是最基本的高可用机制。它通过将主节点的数据复制到从节点来实现,主从节点可以实时同步数据,提高读操作的吞吐量和容灾能力。
- 原理:一个主节点(Master)可以有多个从节点(Slave),主节点处理写请求并将更新同步给从节点(在线slave由主节点推送,新上线的slave增量同步),从节点通常只处理读请求。通过配置多个从节点,当主节点宕机时,依然可以从从节点读取数据。
- 缺点:主节点宕机时需要手动进行主从切换,且在没有哨兵的情况下不具备自动化的故障检测和恢复能力。
- 哨兵模式(Sentinel)
Redis 哨兵模式是在主从复制的基础上,通过引入哨兵来自动监控和管理 Redis 实例的状态,实现更强的高可用性。
- 监控:哨兵会定时检查主节点和从节点的健康状态,检测节点是否宕机。
- 自动故障转移:如果哨兵检测到主节点宕机,会自动进行故障转移(Failover),将某个从节点升级为主节点,并通知其他从节点更新为新的主节点。
- 客户端通知:哨兵还会将主节点的变化通知给客户端,使客户端可以自动切换到新的主节点。
多个哨兵实例通常形成一个哨兵集群,通过投票机制保证故障检测和转移的可靠性。哨兵模式适合中小型高可用场景,但由于每个节点都存储全量数据,扩展性有限。
- Redis Cluster(集群模式)
Redis Cluster 是 Redis 内置的分布式高可用方案,适合需要大规模高可用和高并发的场景。通过分片机制和无中心架构,Cluster 支持横向扩展并增强了容错能力。
- 数据分片:Redis Cluster 将数据划分为 16384 个哈希槽(slots),各节点按槽负责部分数据。这样不仅分摊了存储压力,还提升了读写并发能力。
- 主从架构:每个槽由一个主节点负责存储,为了实现高可用,每个主节点会有一个或多个从节点备份。这样当主节点宕机时,Redis Cluster 可以自动进行主从切换。
- 故障检测和修复:各节点相互通信,通过 Gossip 协议探测节点状态。当节点发生故障时,集群会自动触发故障转移,并保持数据和服务的高可用性。
- 简述redis-cluster集群的原理
- 数据分片
Redis Cluster 将数据分布在集群中的不同节点上。整个集群有 16384 个哈希槽(slots),每个键值对根据哈希值(通过 CRC16 算法)被映射到一个特定的槽号。集群中的每个主节点负责管理一部分哈希槽的数据,从而实现数据的分片存储。
这种分片方式使得 Redis Cluster 支持横向扩展,通过增加节点来分担存储和负载压力,提升了系统的可扩展性。
- 主从复制
Redis Cluster 的每个主节点(master)都可以配置一个或多个从节点(slave)作为备份。主从架构的主要作用在于实现高可用性,避免单点故障:
- 主节点:负责数据的读写操作,数据分片基于主节点进行。
- 从节点:负责备份主节点的数据,不直接处理写请求。在主节点故障时,从节点可以自动接管成为新的主节点,确保数据和服务的持续性。
- 自动故障转移
Redis Cluster 支持自动故障转移。当一个主节点宕机时,集群会通过以下步骤来自动恢复:
- 节点监控:集群中的每个节点会定期通过 Gossip 协议相互通信,了解彼此的状态(存活、故障等)。
- 故障检测:如果多数节点检测到某个主节点不可用,该主节点会被标记为下线(FAIL)。
- 选举新主节点:如果主节点不可用,其从节点会被选举为新的主节点,继续处理该分片的数据请求。
- 客户端通知:Redis Cluster 会将新的主节点信息通知给客户端,确保客户端能够正确地连接到新的主节点。
- 高可用与数据一致性保障
Redis Cluster 通过主从架构和数据冗余来提升高可用性。然而,为了保持高性能,Redis Cluster 的一致性策略是 AP(可用性和分区容忍性),即在分区网络中优先保证服务可用性,可能会出现少量的数据不一致。这种策略适合对高可用性要求较高的场景,但需要结合业务需求权衡一致性和性能的取舍。
Redis Cluster 的优缺点
- 优点:支持数据分片、自动容错、主从架构的高可用性。
- 缺点:不支持多键事务,数据一致性较弱,适合以高可用性和性能优先的场景。
- 介绍一下redis的持久化机制,各有什么优缺点?
- RDB 持久化
RDB(Redis Database Backup) 是通过定期生成数据快照来保存数据库状态的一种方式。Redis 会将内存中的数据快照(键值对)写入磁盘文件(.rdb 文件),该文件包含了 Redis 某一时刻的数据状态(键值对)。
####工作机制
- Redis 根据配置自动触发快照(例如,每 5 分钟有 100 次写入操作时生成快照)。
- 也可以手动使用
SAVE
或BGSAVE
命令生成快照,SAVE
会阻塞 Redis 服务,而BGSAVE
会在后台执行快照生成。
优点
- 数据文件紧凑:RDB 文件是压缩的二进制格式,占用空间少且备份方便。
- 恢复速度快:因为 RDB 文件是快照文件,可以在服务重启时快速加载数据。
- 低资源消耗:RDB 采用周期性备份,平时不会持续对磁盘进行写操作,适合对实时性要求不高的应用场景。
缺点
- 数据持久化不及时:RDB 只能记录快照时的数据,因此在故障情况下,快照生成后的数据可能会丢失。
- 占用额外内存:在生成快照的过程中,Redis 会通过
fork
生成子进程,消耗额外内存;对于大数据量的 Redis 实例,可能会增加系统负载。
适用场景
RDB 持久化更适合于对数据一致性要求不高、允许一定数据丢失的场景,例如数据分析和缓存业务等。
- AOF 持久化
AOF(Append Only File) 通过将每个写操作(如 SET
、INCR
等)记录到日志文件中,从而记录数据库的状态。AOF 文件是一个日志文件,包含了每个修改操作的历史记录。
工作机制
- Redis 将每次写操作追加写入到 AOF 文件,并根据配置决定何时刷新到磁盘。
- Redis 提供了三种同步策略:每次写入、每秒写入和由操作系统决定写入时机。
- AOF 文件会随时间增长,Redis 会定期重写(rewrite)AOF 文件,以减小文件大小。
Redis 是先执行写操作命令后,才将该命令记录到 AOF 日志里的,这么做其实有个好处:
避免额外的检查,如果一条命令不符合协议的语法,那么这条语句是不会被执行的,如果先写入日志,就会导致恢复数据时,这条命令失效,造成了不必要的性能开销
AOF重写机制就是:
读取当前数据库中的所有键值对,然后将每一个键值对用一条命令记录到「新的 AOF 文件」,等到全部记录完后,就将新的 AOF 文件替换掉现有的 AOF 文件。
这样做可以确保AOF只记录有效数据,减少体积(例如我执行了set name wjq,随后又执行了set name wjq++,前者被覆盖是无效的,白占用空间)
优点
- 高数据安全性:AOF 可以提供更实时的数据持久化能力,数据恢复的完整性优于 RDB。
- 易读性和修改性:AOF 文件以文本格式保存操作记录,便于理解和修改,适合用于灾难恢复。
缺点
- 文件体积较大:与 RDB 文件相比,AOF 文件较大,且写操作较多时会频繁写入磁盘。
- 恢复速度慢:由于需要逐条执行操作日志中的指令,数据恢复速度不如 RDB 快。
- 消耗更多资源:AOF 需要持续写入操作日志,磁盘 I/O 操作频繁,可能影响 Redis 性能。
适用场景
AOF 适合对数据安全性要求较高的业务场景,例如金融支付、订单管理等场景。
- RDB 与 AOF 混合持久化
Redis 4.0 引入了 RDB 和 AOF 的混合持久化机制。通过这种方式,Redis 在后台持久化时会先将内存快照(RDB)写入 AOF 文件,并在末尾追加新的增量日志。
优点
- 加快数据恢复:RDB 的快照能够快速恢复大部分数据,而 AOF 的增量日志确保了数据的实时性,保证了高效恢复和较小的数据丢失风险。
-
Redis的淘汰策略了解哪些?
-
分析redis的事务?
由于redis命令处理是单线程的,具有天然的隔离性,
redis 不支持回滚;即使事务队列 中的某个命令在执行期间出现了错误,整个事务也会继续执行 下去,直到将事务队列中的所有命令都执行完毕为止
持久性:AOF或RDB -
你redis常用的数据结构以及在业务中使用的场景?
Hash实现未读消息计数、session更新时间,zset实现排行榜 -
Redis内存数据库的内存指的是共享内存么?
不是,是redis进程独占的用户态内存 -
redis单线程结构有什么优势?有什么问题?
1.单线程意味着没有锁和竞争条件,避免了多线程中的锁管理、死锁等并发问题,从而简化了代码逻辑,提高了可靠性 -
多线程程序中,线程切换会产生上下文切换开销,尤其是当操作系统频繁调度时。单线程的 Redis 避免了这种开销,性能较为稳定
问题:- Redis 单线程只能使用单核 CPU,难以利用多核 CPU 的性能,因此在 CPU 密集型场景下性能会受限。
- 单线程结构意味着 Redis 的命令执行是串行的,在需要高吞吐量的场景下,单线程模型可能无法满足需求,特别是对高频写入和复杂数据结构的大量更新操作。
解决:可以通过 Redis 分片(如 Redis Cluster)将数据分配到多个节点,从而实现数据的分布式存储和访问,在一定程度上缓解单线程带来的性能限制
-
Redis为什么这么快?(网络、数据结构)
-
单线程模型
- Redis 的核心使用单线程来处理客户端请求。这消除了多线程中常见的线程切换和锁竞争问题,避免了上下文切换的开销。
- 单线程模型使得 Redis 在处理每个命令时都非常高效,并且通过事件驱动的 I/O 多路复用机制(如
epoll
)来处理大量并发连接,避免了复杂的并发控制。
-
高效的内存管理
- Redis 将数据存储在内存中,这使得其读写速度极快,因为内存访问速度比磁盘要快得多。
-
数据结构选择
- Redis 提供了多种高效的数据结构,包括:
- 字符串(String):Redis 中最基本的类型,存储简单数据,如数字或文本。其操作非常简单,速度非常快。
- 哈希表(Hash):适合存储对象。哈希表的查找时间复杂度是 O(1),在 Redis 中存储的是经过优化的哈希结构,使得它的操作效率非常高。
- 列表(List):双向链表实现,适用于快速的推入和弹出操作。对于队列等应用场景非常合适。
- 集合(Set):无序且不重复的集合,底层使用哈希表实现,支持高效的并集、交集、差集等操作。
- 有序集合(Sorted Set):在集合的基础上加上了排序功能,底层使用跳表(Skip List)实现,支持高效的范围查询和排序。
- 位图(Bitmap):用于处理大规模的二进制数据,支持非常高效的按位操作。
- 这些数据结构在 Redis 中的实现都非常高效,优化了操作复杂度和存储方式,能够满足不同业务场景的需求。
- Redis 提供了多种高效的数据结构,包括:
-
IO 多路复用(事件驱动)
- Redis 使用 epoll(Linux)等 I/O 多路复用技术来高效地处理并发客户端连接。这使得即使有数万个客户端同时连接,Redis 也能有效地管理请求,而无需为每个连接创建一个线程。
- Redis 使用 事件循环模型,通过一个单独的线程循环检查所有连接和任务,选择合适的操作(如读写请求),使得其处理请求的效率非常高。
-
管道化(Pipeline)
- Redis 支持 管道化,即客户端可以一次性发送多个命令,而不需要等待每个命令的响应。这可以显著减少请求的往返延迟,提高吞吐量。
- 管道化非常适合批量操作,尤其在高并发的场景下,可以大大提升性能。
-
-
集群和分布式分别用来解决什么问题?
-
redis大key问题了解吗?
在Redis中,"大key"通常指的是占用内存非常大的单个键或数据结构。它们可以是:
• 大字符串(String):单个字符串值非常大(比如超过几MB,甚至GB)。
• 大哈希(Hash):包含大量字段的哈希表。
• 大列表(List):包含大量元素的列表。
• 大集合(Set)、有序集合(Sorted Set):包含大量元素的集合。
• 大位图(Bitmap)或HyperLogLog等其他数据结构。
大key引发的问题
-
内存占用高:Redis是一个内存数据库,所有数据都保存在内存中。如果某个键的数据量非常大,就会占用大量的内存空间。特别是在高并发应用中,大key会导致内存压力过大,可能导致Redis实例无法容纳更多数据或发生OOM(Out Of Memory)错误。
-
性能问题:
o 慢操作:大key的操作(例如,获取、删除、修改)可能需要更长的时间来完成。这会影响Redis的响应时间,导致整体性能下降。特别是当你执行像GET、DEL、HGETALL这样的操作时,操作大key可能需要大量的CPU和内存资源。
o 阻塞:大key的操作有时会阻塞Redis的事件循环,影响到其他正常请求的处理。Redis是单线程的,执行大key操作时会占用线程过长的时间,从而导致其他请求的响应变慢。
解决:
分割大key:
• 如果某个数据结构(例如,列表、哈希、集合等)非常大,可以考虑将其分割成多个小的子键。这样可以避免在操作时造成性能瓶颈。
• 比如,长列表可以通过切分成多个小列表存储,或者将大哈希拆分成多个小哈希
避免大key的创建:
• 在设计Redis存储结构时,尽量避免创建大key。例如,尽量避免将大量的日志、会话数据或用户信息存储在Redis中,除非有明确的分割策略。
设置合理的过期时间:
• 如果大key的生命周期较短,可以考虑为这些大key设置合理的过期时间,确保它们不会长期占用Redis的内存。 -
微博上面的热搜,打在了集群的分片上,分片扛不住怎么办?
当热搜数据集中在某些分片上,导致分片负载过高时,可以采取以下策略:
• 扩容分片:增加更多的分片,重新分配哈希槽,将热搜数据分散到新的节点上。
• 使用热点缓存(Local Cache):在分片外部,通过额外的缓存层来处理热点数据,减轻原分片的压力。例如,可以将热搜数据缓存到本地内存或者CDN中,减少对Redis的访问频率。
• 数据打散:将热搜数据打散存储,比如通过增加前缀或后缀,将同一类数据散布到不同的分片上,从而均衡负载。 -
用限流解决,有哪些实现限流的方法?
限流是一种控制请求量的方式,常见的实现方法包括:
• 令牌桶算法:预先生成一定数量的“令牌”,每次请求消耗一个令牌,令牌用完则限流,适用于控制请求速率。
• 漏桶算法:固定请求处理速度的队列结构,请求进入漏桶队列后以固定速率被处理,避免瞬时高并发的请求挤满系统。
• 计数器法:通过在固定时间窗口内对请求计数,超出预设的阈值即进行限流。
• 滑动窗口计数:改进计数器法,将请求窗口划分成更小的子窗口,以增加灵活性。适合流量不均匀的场景。 -
限流的话,用户看到的一个页面就是一个空白页面,对用户不够友好,还有什么别的方案?
在限流的情况下直接返回空白页面体验较差,可以采用以下策略:
• 降级服务:提供简化内容或低优先级的缓存数据,而非直接返回空白页面。例如,可以提供一个热点内容的简略列表,或返回一个带提示的默认页面。
• 预生成和冗余缓存:可以在多个分片或不同存储节点上冗余缓存热点内容,使得每个请求都能从最近的缓存中获取数据,避免热点数据压力集中。
• 缓存打散:通过在不同分片上存储不同版本的同一数据,避免单个分片被热点请求压垮 -
现在如果我不知道哪个帖子会成为热搜帖子,这种情况怎么处理?
当无法预先知道哪些帖子会成为热搜时,可以采取以下措施:
• 多级缓存策略:通过本地缓存、分布式缓存(Redis)、外部缓存(如CDN)组成多级缓存链路。用户的请求会优先命中靠近的数据层,从而减轻后端数据库的压力。
• 热点检测和动态缓存调整:实时监控请求量,自动检测热点数据,并将这些数据存入缓存中。通过动态调整缓存的存储层级和分布,提升响应效率。
• 异步刷新和负载均衡:对热点数据进行异步刷新,让更多请求访问缓存副本。此外,使用负载均衡将请求引导到多个缓存服务器或分片,避免单点压力过大。
原文地址:https://blog.csdn.net/2303_77208351/article/details/143695990
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!