📕我是廖志伟,一名Java开发工程师、《Java项目实战——深入理解大型互联网企业通用技术》(基础篇)、(进阶篇)、(架构篇)清华大学出版社签约作家、Java领域优质创作者、优快云博客专家、阿里云专家博主、51CTO专家博主、产品软文专业写手、技术文章评审老师、技术类问卷调查设计师、幕后大佬社区创始人、开源项目贡献者。
📘拥有多年一线研发和团队管理经验,研究过主流框架的底层源码(Spring、SpringBoot、SpringMVC、SpringCloud、Mybatis、Dubbo、Zookeeper),消息中间件底层架构原理(RabbitMQ、RocketMQ、Kafka)、Redis缓存、MySQL关系型数据库、 ElasticSearch全文搜索、MongoDB非关系型数据库、Apache ShardingSphere分库分表读写分离、设计模式、领域驱动DDD、Kubernetes容器编排等。不定期分享高并发、高可用、高性能、微服务、分布式、海量数据、性能调优、云原生、项目管理、产品思维、技术选型、架构设计、求职面试、副业思维、个人成长等内容。

🌾阅读前,快速浏览目录和章节概览可帮助了解文章结构、内容和作者的重点。了解自己希望从中获得什么样的知识或经验是非常重要的。建议在阅读时做笔记、思考问题、自我提问,以加深理解和吸收知识。阅读结束后,反思和总结所学内容,并尝试应用到现实中,有助于深化理解和应用知识。与朋友或同事分享所读内容,讨论细节并获得反馈,也有助于加深对知识的理解和吸收。💡在这个美好的时刻,笔者不再啰嗦废话,现在毫不拖延地进入文章所要讨论的主题。接下来,我将为大家呈现正文内容。

一、核心数据结构
Redis的核心数据结构是其性能和功能的关键,以下对每个数据结构进行深入的技术实现细节解析:
-
特殊结构
-
HyperLogLog(基数统计):HyperLogLog是一种基于概率算法的数据结构,其核心是使用一个固定大小的哈希表来估计一个超集的大小。这个超集包含了原始集合的所有元素以及一些随机生成的元素。在实现上,Redis使用一个64位的整数来存储每个哈希表的值,通过多个这样的哈希表来估计不同基数的数据集。HyperLogLog的优势在于其内存效率极高,即使是非常大的数据集,其内存占用也非常小。
-
Bitmap(位图操作):Bitmap通过位操作来表示数据集合,每个位对应一个元素。在Redis中,Bitmap可以高效地实现计数、存在性检查等操作。例如,使用Bitmap可以快速地统计一个集合中特定元素的出现次数,或者检查一个元素是否存在于集合中。
-
GEO(地理空间索引):GEO数据结构存储地理位置信息,并支持诸如距离查找、范围查找等地理空间查询。在Redis中,GEO使用一个空间索引来存储地理位置信息,并通过空间几何算法来执行查询。这种数据结构在地图服务、位置信息服务等领域非常有用。
-
-
底层实现
-
跳跃表(Sorted Set实现):Redis的跳跃表是一种数据结构,它通过多级索引来提高查找效率。跳跃表在实现时,通过维护多个层级来模拟有序数组,每个层级包含部分数据,且每个层级都包含指向下一层级的指针。这种结构在Redis中用于实现有序集合(Sorted Set),提供了类似于有序数组的操作,同时保持了较高的查找效率。
-
压缩列表(List/Hash优化存储):压缩列表是一种特殊的内存数据结构,用于优化小列表和哈希表的存储。在Redis中,当列表或哈希表中的元素数量较少时,使用压缩列表可以节省内存空间。压缩列表通过将多个小元素紧凑地存储在单个结构中来优化内存使用。
-
快速列表(QuickList):QuickList是Redis用于优化列表数据结构的实现,它结合了快速列表和压缩列表的优点。QuickList在内部使用多个压缩列表和快速列表来存储数据,这样可以在保持高效插入和删除操作的同时,也支持快速的随机访问。
-
二、持久化机制
Redis的持久化机制确保了数据的持久存储,以下是每个持久化机制的技术实现细节:
-
RDB
-
快照触发条件:Redis可以通过手动触发或者根据配置自动触发RDB快照。自动触发通常基于时间间隔或内存限制。在实现上,Redis使用一个后台线程定期检查是否需要执行快照。
-
COW(写时复制)机制:Redis在执行写操作时,会先复制一份数据,然后修改复制品,从而实现数据的持久化。这种机制确保了在数据写入过程中,原始数据不会受到影响。
-
-
AOF
-
重写压缩流程:AOF记录所有写操作,通过重写机制来压缩记录,减少文件大小。重写过程会创建一个新的AOF文件,其中只包含自上次重写以来发生的写操作。
-
fsync策略:fsync策略包括always/everysec/no,用于控制数据同步到磁盘的频率。always表示每次写操作都会同步到磁盘,everysec表示每秒同步一次,no表示由操作系统决定同步频率。选择合适的fsync策略需要在性能和数据安全性之间进行权衡。
-
三、高可用方案
Redis的高可用方案提供了数据冗余和故障恢复的能力,以下是每个方案的实现细节:
-
哨兵模式
-
主观/客观下线判定:哨兵通过主观和客观的方式判断Redis实例是否下线。主观下线是指哨兵认为一个实例已经无法正常响应,而客观下线是指多个哨兵都认为一个实例已经无法正常响应。
-
领导者选举流程:当主节点下线时,哨兵会进行领导者选举,以选择新的主节点。选举过程遵循Redis集群的选举算法,确保新的主节点具有足够的性能和稳定性。
-
故障转移时序控制:故障转移时序控制确保了故障转移的有序进行。在故障转移过程中,哨兵会确保所有的从节点都同步了最新的数据,然后才会进行故障转移。
-
-
集群模式
-
哈希槽分配算法:Redis集群通过哈希槽将数据分片,每个节点负责一部分哈希槽的数据。哈希槽的分配通常基于哈希算法,确保数据分布的均匀性。
-
ASK/MOVED重定向:当客户端请求的数据不在当前节点时,Redis会返回ASK/MOVED重定向指令。客户端收到重定向后,会根据指令找到数据所在节点并重新发送请求。
-
Gossip协议通信:Gossip协议用于节点间的信息交换,保持集群状态的一致性。Gossip协议通过周期性地交换节点信息来更新集群状态。
-
四、高级特性
Redis的高级特性增强了其功能性和灵活性,以下是每个特性的实现细节:
-
内存管理
-
LRU/LFU淘汰策略:Redis使用LRU(最近最少使用)和LFU(最少使用频率)策略来淘汰内存中的数据。LRU通过记录每个元素的访问时间来淘汰最久未访问的元素,而LFU则淘汰使用频率最低的元素。
-
内存碎片整理:Redis定期进行内存碎片整理,优化内存使用。内存碎片整理的过程包括合并相邻的空闲内存块,减少内存碎片。
-
-
事务控制
-
WATCH/MULTI/EXEC:Redis事务通过WATCH命令监视键,MULTI开始事务,EXEC执行事务。在实现上,Redis在执行事务时,会先记录所有命令,然后一次性执行这些命令。
-
悲观锁实现:Redis可以使用SETNX等命令实现悲观锁。SETNX命令用于设置一个键的值,如果键不存在则设置成功,否则失败。
-
Lua脚本原子性:Lua脚本在Redis中以原子方式执行,确保操作的原子性。在实现上,Redis会先将Lua脚本编译成字节码,然后一次性执行这些字节码。
-
五、扩展组件
Redis的扩展组件丰富了其应用场景,以下是每个扩展组件的实现细节:
-
Redis模块
-
RediSearch(全文检索):RediSearch通过扩展Redis的功能,提供了全文检索功能。在实现上,RediSearch使用倒排索引来存储和检索文本数据。
-
RedisGraph(图数据库):RedisGraph允许存储和查询图数据。在实现上,RedisGraph使用图遍历算法来执行查询。
-
RedisTimeSeries(时序数据):RedisTimeSeries用于存储和查询时序数据。在实现上,RedisTimeSeries使用时间窗口和索引来优化时序数据的存储和查询。
-
-
生态工具
-
RedisInsight(可视化监控):RedisInsight通过Web界面提供Redis实例的可视化监控和管理。在实现上,RedisInsight通过Redis的命令行工具和API来获取和展示信息。
-
RedisBloom(布隆过滤器):RedisBloom实现布隆过滤器,用于快速的数据存在性检查。在实现上,RedisBloom使用多个哈希函数和一个位数组来存储数据。
-
twemproxy(分片代理):twemproxy作为代理,可以将请求分片到不同的Redis节点。在实现上,twemproxy使用哈希算法来决定请求应该发送到哪个Redis节点。
-
六、性能优化
Redis的性能优化涉及客户端和服务端,以下是每个优化策略的实现细节:
-
客户端
-
Pipeline批处理:通过Pipeline可以将多个命令打包成一个请求发送,减少网络延迟。在实现上,客户端将多个命令序列化后发送到Redis,Redis一次性处理这些命令,并将结果返回给客户端。
-
连接池配置:合理配置连接池,可以减少连接创建和销毁的开销。在实现上,客户端维护一个连接池,重复使用连接来减少连接创建和销毁的次数。
-
-
服务端
-
多IO线程:Redis使用多IO线程来处理网络请求,提高并发处理能力。在实现上,Redis使用线程池来管理IO线程,每个线程负责处理一部分网络请求。
-
后台线程优化:Redis的后台线程执行定期的任务,如内存碎片整理、AOF持久化等。在实现上,Redis使用多线程来并行执行这些后台任务。
-
大key拆分方案:对于大key,可以通过拆分的方式减少内存消耗和提高处理速度。在实现上,可以将大key拆分成多个小key,或者将大key中的数据分散存储到不同的key中。
-
📥博主的人生感悟和目标

- 💂 博客主页: Java程序员廖志伟希望各位读者大大多多支持用心写文章的博主,现在时代变了,信息爆炸,酒香也怕巷子深,博主真的需要大家的帮助才能在这片海洋中继续发光发热,所以,赶紧动动你的小手,点波关注❤️,点波赞👍,点波收藏⭐,甚至点波评论✍️,都是对博主最好的支持和鼓励!
- 👉 开源项目: Java程序员廖志伟
- 🌥 哔哩哔哩: Java程序员廖志伟
- 🎏 个人社区: Java程序员廖志伟
- 🔖 个人微信号:
SeniorRD

📙经过多年在优快云创作上千篇文章的经验积累,我已经拥有了不错的写作技巧。同时,我还与清华大学出版社签下了四本书籍的合约,并将陆续出版。这些书籍包括了基础篇、进阶篇、架构篇的📌《Java项目实战—深入理解大型互联网企业通用技术》📌,以及📚《解密程序员的思维密码--沟通、演讲、思考的实践》📚。具体出版计划会根据实际情况进行调整,希望各位读者朋友能够多多支持!
🔔如果您需要转载或者搬运这篇文章的话,非常欢迎您私信我哦~