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

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

一、核心数据结构
Redis的核心数据结构是其高效性能的关键,以下是几种特殊数据结构的详细描述及其技术实现细节:
1. 特殊结构
(1) HyperLogLog(基数统计)
HyperLogLog是一种用于估计集合中元素基数的算法,它利用了哈希函数的随机性以及计数器的累积。在Redis中,实现HyperLogLog的数据结构包含多个计数器,每个计数器对应一个哈希函数的输出。当插入一个新元素时,通过哈希函数映射到对应的计数器,并增加计数器的值。当需要估计基数时,对所有的计数器取对数后求和,然后应用一个修正公式来得到最终结果。这种算法具有很高的空间效率,因为它的内存占用与数据集的大小几乎无关。
(2) Bitmap(位图操作)
Redis的Bitmap使用单个位来表示布尔值,通过位操作进行数据的存储和检索。位图非常适合存储大量的布尔值,例如用户在线状态、访问权限等。Redis提供了位图的高效操作命令,如GETBIT、SETBIT、BITCOUNT等,可以快速地对单个位或连续的位进行操作。
(3) GEO(地理空间索引)
GEO使用GEOHash算法将地理坐标转换为字符串,以实现地理位置数据的存储和查询。GEOHash算法通过将经纬度映射到一个固定长度的字符串,将地理坐标编码成一个紧凑的表示形式,便于存储和索引。Redis提供了GEOADD、GEOPOS、GEODIST等命令,支持地理坐标的存储、查询和距离计算。
2. 底层实现
(1) 跳跃表(Sorted Set实现)
跳跃表是一种非平衡的数据结构,它通过多个有序层来模拟有序数组的快速查找、插入和删除操作。在Redis中,跳跃表使用多个有序层,每个有序层包含多个索引节点,通过指针连接到下一层。这种结构在保持数据有序的同时,提供了快速的查找性能。
(2) 压缩列表(List/Hash优化存储)
Redis的压缩列表是一种紧凑的数据结构,用于存储小数据类型的集合。压缩列表将多个小元素存储在一个连续的内存块中,减少了内存的使用和分配开销。压缩列表支持动态增长和缩减,当元素数量增加时,会自动转换为更复杂的数据结构。
(3) 快速列表(QuickList)
QuickList结合了链表和数组的优点,适用于频繁的插入和删除操作。QuickList在链表的每个节点后面附加一个固定大小的数组,用于加速插入和删除操作。当数组满时,会自动扩展数组大小,从而平衡了时间和空间的开销。
二、持久化机制
1. RDB(快照触发条件)
RDB持久化通过定期生成数据快照来备份数据库。触发快照的条件包括:
- 手动触发:通过执行SAVE或BGSAVE命令手动触发快照。
- 定时触发:通过配置文件中的save指令,设置特定的时间间隔和内存限制。
- 内存溢出触发:当内存使用达到配置的阈值时,自动触发快照。
2. COW(写时复制)机制
COW机制在RDB持久化中用于优化写操作。当执行写操作时,Redis会创建一个新的数据副本,并在副本上进行修改,而原数据保持不变。当快照完成后,会将副本中的数据写入到快照文件中。
3. AOF(重写压缩流程)
AOF持久化记录了Redis的所有写操作。重写压缩流程包括:
- 合并重复写操作:删除重复的写操作记录,以减少文件大小。
- 删除已持久化的数据:删除已包含在AOF中的数据记录,避免数据重复。
- 压缩数据:使用压缩算法对AOF文件进行压缩,减少存储空间。
4. fsync策略(always/everysec/no)
fsync策略决定了Redis同步磁盘的频率。always表示每次写操作都同步磁盘,everysec表示每秒同步一次,no表示完全依赖操作系统进行同步。选择合适的fsync策略需要平衡性能和数据安全性。
三、高可用方案
1. 哨兵模式
哨兵模式通过监控Redis集群的多个节点来实现故障转移和节点下线判定。哨兵节点负责监控主节点的状态,当检测到主节点故障时,会启动故障转移流程,选择新的主节点。
2. 主观/客观下线判定
哨兵模式中的节点下线判定分为主观下线和客观下线。主观下线是指单个哨兵认为节点不可用,而客观下线是指多数哨兵认为节点不可用。客观下线判定需要多数哨兵节点达成一致意见。
3. 领导者选举流程
在哨兵模式中,当主节点故障后,哨兵将进行领导者选举,以确定新的主节点。选举过程包括:哨兵节点投票、计算投票结果、确定新的主节点等步骤。
4. 故障转移时序控制
故障转移时序控制是指在故障转移过程中,对各个阶段进行有序控制,以确保数据的一致性和系统的稳定性。控制步骤包括:同步主节点数据、通知从节点切换到新主节点、更新节点信息等。
5. 集群模式
集群模式将多个Redis节点组成一个逻辑集群,通过哈希槽分配算法将数据分散到各个节点,实现数据的分布式存储。集群模式支持节点故障转移、数据迁移等特性。
6. 哈希槽分配算法
Redis集群采用哈希槽分配算法,将数据映射到特定的哈希槽。哈希槽是一个虚拟的概念,用于将数据分配到不同的节点。哈希槽的分配方式可以保证数据分布的均匀性和一致性。
7. ASK/MOVED重定向
ASK/MOVED重定向是一种在集群中处理请求的机制。当请求的数据不在当前节点时,Redis会返回ASK/MOVED重定向,指导客户端向正确的节点发送请求。
8. Gossip协议通信
Gossip协议是一种用于集群节点间通信的协议。它通过广播和接收消息,实现节点间的状态同步。Gossip协议具有高效、可靠、可扩展等特点。
四、高级特性
1. 内存管理
(1) LRU/LFU淘汰策略
LRU(最近最少使用)和LFU(最不常用)是Redis采用的内存淘汰策略。LRU通过记录数据的使用时间,当内存不足时,淘汰最近最少使用的元素。LFU通过记录数据的使用频率,淘汰使用频率最低的元素。
(2) 内存碎片整理
Redis会定期进行内存碎片整理,以优化内存使用。碎片整理通过合并内存碎片,释放未使用的内存空间,提高内存利用率。
(3) 惰性删除机制
惰性删除机制是指Redis在删除数据时,不是立即释放内存,而是等待内存使用达到一定阈值时,再进行释放。这种机制可以减少内存释放的频率,提高性能。
2. 事务控制
(1) WATCH/MULTI/EXEC
WATCH/MULTI/EXEC是Redis的事务控制机制。WATCH命令用于监控数据,MULTI命令表示开始事务,EXEC命令表示执行事务。这种机制可以保证事务中的多个命令原子性地执行。
(2) 悲观锁实现
Redis可以通过SETNX命令实现悲观锁。SETNX命令尝试设置键的值,如果键已存在,则返回0,否则返回1。通过这种方式,可以确保对数据的独占访问。
(3) Lua脚本原子性
Redis支持将多个命令封装成Lua脚本执行,保证Lua脚本在执行过程中的原子性。Lua脚本执行过程中,Redis会阻塞其他命令的执行,直到Lua脚本执行完成。
五、扩展组件
1. Redis模块
Redis模块是一种扩展Redis功能的方式,允许用户自定义命令和数据结构。用户可以通过编写C语言代码来创建模块,并将其加载到Redis中。
2. 生态工具
(1) RedisInsight(可视化监控)
RedisInsight是一款可视化监控工具,用于监控Redis的性能和状态。它提供了实时监控、历史数据分析、告警等功能。
(2) RedisBloom(布隆过滤器)
RedisBloom是一种基于Redis的布隆过滤器,用于快速判断元素是否存在于集合中。布隆过滤器具有很高的空间效率,适用于需要快速判断元素存在性的场景。
(3) twemproxy(分片代理)
twemproxy是一种分片代理,可以将请求分发到多个Redis节点,提高性能。它支持多种分片策略,如按键值范围分片、按哈希值分片等。
六、性能优化
1. 客户端
(1) Pipeline批处理
Pipeline批处理将多个命令打包在一起,减少网络往返次数,提高性能。客户端可以将多个命令发送到Redis,Redis会顺序执行这些命令,并将结果返回给客户端。
(2) 连接池配置
连接池可以缓存多个Redis连接,减少连接建立和销毁的开销。通过配置合理的连接池参数,可以提高客户端的性能。
(3) 读写分离策略
读写分离策略可以将读操作和写操作分别发送到不同的节点,提高性能。读操作可以发送到从节点,写操作发送到主节点。
2. 服务端
(1) 多IO线程
多IO线程可以将读写操作并行化,提高性能。Redis可以使用多线程来处理客户端请求,从而提高并发处理能力。
(2) 后台线程优化
后台线程可以执行耗时的操作,如数据压缩、持久化等,提高性能。Redis可以通过配置后台线程的数量和优先级来优化后台线程的性能。
(3) 大key拆分方案
对于占用内存较大的key,可以将其拆分成多个小key,降低内存压力。拆分大key可以减少内存的使用,提高Redis的性能。
📥博主的人生感悟和目标

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

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