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

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

一、核心数据结构
Redis作为一款高性能的键值存储系统,其核心数据结构的设计决定了其性能和灵活性。以下将深入解析Redis中这些核心数据结构的技术实现细节。
特殊结构:
-
HyperLogLog(基数统计):HyperLogLog是一种基于概率的数据结构,通过哈希函数将输入数据映射到有限空间中,并通过估计算法近似计算集合的基数。在Redis中,HyperLogLog使用一个固定大小的数组来存储哈希值,并通过泊松近似公式来计算集合的基数。这种数据结构特别适用于实时统计大规模数据集的基数,如网站访问量、用户数等。
-
Bitmap(位图操作):Bitmap是一种使用位(bit)来表示数据的结构,每个位可以表示一个状态(如存在或不存在)。在Redis中,Bitmap可以用来存储大量的布尔值,或者表示大量的状态信息,如活跃用户、在线状态等。位图操作可以通过位运算来完成,如AND、OR、NOT等。
-
GEO(地理空间索引):GEO数据结构允许用户存储地理位置信息,并支持基于地理位置的查询。在Redis中,GEO数据结构通过存储经纬度信息,并结合空间索引算法来实现地理位置的查询。GEO数据结构支持多种查询,如计算两个地理位置之间的距离、查找指定范围内的元素等。
底层实现:
-
跳跃表(Sorted Set实现):跳跃表是一种数据结构,它通过多级索引来提高搜索效率。在Redis中,跳跃表用于实现Sorted Set数据结构,它支持对有序集合的快速搜索、插入和删除操作。跳跃表通过维护多级索引,将数据分布到多个层级,从而提高了搜索效率。
-
压缩列表(List/Hash优化存储):压缩列表是一种紧凑的内部表示,用于存储列表和哈希表中的元素。当数据量较小时,压缩列表可以显著减少内存占用。压缩列表通过将多个元素合并成一个结构体来减少内存占用,并通过指针来访问其他元素。
-
快速列表(QuickList):QuickList结合了链表和数组的优点,适用于存储较长的列表。QuickList在列表较短时使用数组,在列表较长时使用链表,从而在保持数组的高效访问性能的同时,避免链表在列表较小时的高内存开销。
二、持久化机制
Redis的持久化机制确保了数据的持久性和安全性。以下是Redis持久化机制的技术实现细节。
RDB(快照触发条件):
- RDB(Redis Database File)通过定期创建数据快照来持久化数据。触发RDB快照的条件包括:
- 定时触发:根据配置的save参数,如save 900 1,Redis会定期检查是否有键在900秒内被修改,如果满足条件则触发RDB持久化。
- 手动触发:通过执行save或bgsave命令,可以立即触发RDB持久化。
COW(写时复制)机制:
- COW(Copy On Write)机制在RDB持久化过程中发挥作用。当Redis启动时,它会加载RDB文件,并创建一个数据副本用于修改,而原始数据保持不变。当修改完成后,原始数据会被丢弃,从而节省内存。
AOF(重写压缩流程):
- AOF(Append Only File)持久化机制记录了Redis执行的每一条写命令。触发AOF重写的条件包括:
- 文件大小增长:根据配置的appendfsync参数,如appendfsync everysec,当AOF文件大小超过64MB时,触发AOF重写。
- 手动触发:通过执行bgrewriteaof命令,可以立即触发AOF重写。
fsync策略(always/everysec/no):
- fsync参数决定了Redis何时将AOF缓冲区中的数据写入磁盘。可选值包括:
- always:每次写操作后立即执行fsync。
- everysec:每秒执行一次fsync。
- no:不执行fsync,由操作系统决定何时写入磁盘。
三、高可用方案
Redis的高可用方案主要包括哨兵模式和集群模式,以下是这两种模式的技术实现细节。
哨兵模式:
- 哨兵模式通过监控多个Redis节点,实现故障检测和故障转移。其关键点包括:
- 主观/客观下线判定:哨兵节点根据自身信息判断节点是否下线,若多个哨兵节点都认为某个节点下线,则认为该节点客观下线。
- 领导者选举流程:哨兵节点通过选举产生领导者,领导者负责故障转移和故障恢复。
- 故障转移时序控制:领导者负责将下线节点上的数据迁移到其他节点,并更新哨兵节点和客户端的配置。
集群模式:
- 集群模式通过将多个Redis节点组织成一个集群,实现数据的分片和高可用。其关键点包括:
- 哈希槽分配算法:集群使用哈希槽将数据分片,每个节点负责一部分哈希槽。
- ASK/MOVED重定向:当客户端请求的数据不在当前节点时,节点会返回ASK/MOVED重定向信息,指导客户端向正确的节点发送请求。
- Gossip协议通信:集群节点通过Gossip协议交换信息,如节点状态、哈希槽分配等。
四、高级特性
Redis的高级特性包括内存管理、事务控制、Lua脚本等,以下是这些特性的技术实现细节。
内存管理:
- LRU/LFU淘汰策略:Redis使用LRU(最近最少使用)和LFU(最少使用频率)淘汰策略,根据数据的使用情况淘汰内存。LRU通过维护一个链表来记录最近访问的数据,当内存不足时,淘汰最早访问的数据。LFU则通过维护一个哈希表来记录每个数据的使用频率,当内存不足时,淘汰使用频率最低的数据。
事务控制:
- WATCH/MULTI/EXEC:Redis事务通过WATCH/MULTI/EXEC命令实现。WATCH命令用于监控键值对,当键值对在事务执行期间被修改时,事务将被中断。MULTI命令开始事务,EXEC命令执行事务。
悲观锁实现:
- Redis通过SETNX命令实现悲观锁。当SETNX命令返回1时,表示锁成功;返回0时,表示锁已被其他客户端获取。
Lua脚本原子性:
- Redis支持Lua脚本,并保证Lua脚本在执行过程中的原子性。当Lua脚本开始执行时,Redis会锁定所有相关的键,确保Lua脚本在执行过程中不会被其他命令中断。
五、扩展组件
Redis的扩展组件和生态工具丰富了其功能和应用场景,以下是这些组件和工具的技术实现细节。
Redis模块:
- RediSearch:基于Redis的全文检索模块,使用倒排索引来存储和检索文本数据。
- RedisGraph:基于Redis的图数据库模块,使用邻接表和路径算法来存储和查询图数据。
- RedisTimeSeries:基于Redis的时序数据模块,使用时间窗口和时间序列算法来存储和查询时序数据。
生态工具:
- RedisInsight:Redis可视化监控工具,使用Web界面和JavaScript来展示Redis的实时数据和性能指标。
- RedisBloom:基于Redis的布隆过滤器模块,使用布隆过滤器和哈希函数来快速判断元素是否存在于集合中。
- twemproxy:Redis分片代理,使用多线程和事件驱动模型来实现Redis集群的读写分离和负载均衡。
六、性能优化
Redis的性能优化主要包括客户端和服务端两个方面,以下是这些优化的技术实现细节。
客户端:
- Pipeline批处理:将多个命令打包成一个批量请求,减少网络往返时间。Redis客户端使用pipeline机制,将多个命令发送到服务器,服务器将这些命令作为一个批次来处理,然后一次性返回结果。
连接池配置:合理配置连接池大小,提高并发处理能力。连接池管理器负责创建和回收连接,并通过连接池来复用连接,减少连接创建和销毁的开销。
读写分离策略:将读操作和写操作分配到不同的节点,提高系统吞吐量。Redis支持读写分离,客户端可以将读操作发送到从节点,将写操作发送到主节点,从而提高系统吞吐量。
服务端:
- 多IO线程:使用多线程处理IO操作,提高系统并发处理能力。Redis使用多线程来处理客户端连接,每个线程负责处理一定数量的客户端连接,从而提高并发处理能力。
后台线程优化:优化后台线程的工作方式,如AOF持久化线程。Redis使用后台线程来处理持久化和复制等任务,优化后台线程的工作方式可以提高系统性能。
大key拆分方案:将大key拆分成多个小key,提高数据访问效率。在Redis中,大key可能会导致内存碎片和缓存问题,通过将大key拆分成多个小key,可以提高数据访问效率和内存利用率。
📥博主的人生感悟和目标

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

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