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

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

一、核心数据结构
Redis,作为一款高性能的键值数据库,其核心数据结构是其性能和功能的基础。以下是Redis中几个特殊结构的详细介绍,包括其技术实现细节:
1. 特殊结构
(1)HyperLogLog(基数统计)
HyperLogLog是一种概率数据结构,它通过一个非常小的数据结构来估计一个集合中不重复元素的大致数量。其技术实现细节如下:
- 哈希函数:HyperLogLog使用多个哈希函数来确保不同的元素映射到不同的位置,从而减少估计误差。
- 计数器数组:它使用一个固定大小的计数器数组来记录每个哈希值出现的次数,数组的大小为2^14,每个计数器使用64位。
- 累积:每次插入新元素时,计算其哈希值,并在计数器数组中增加计数。如果计数器达到最大值,则重置该计数器。
- 估计:通过累积的计数器,使用泊松分布公式来估计元素的数量。
(2)Bitmap(位图操作)
Bitmap使用位来表示集合,每个位对应一个布尔值。其技术实现细节如下:
- 位操作:通过位操作来设置、获取和检查集合中的元素。
- 空间效率:通过将每个元素映射到一个位,大大减少了存储空间的需求。
- 内存对齐:为了保证内存访问的效率,Bitmap通常以字节为单位进行内存对齐。
(3)GEO(地理空间索引)
GEO数据结构允许存储具有地理坐标的值,并支持基于地理空间查询。其技术实现细节如下:
- 坐标存储:每个地理坐标使用两个浮点数来存储纬度和经度。
- 空间网格:将地球表面划分为多个空间网格,每个网格存储在该网格内的地理坐标。
- 范围查询:通过空间网格快速定位到包含目标坐标的网格,从而实现范围查询。
2. 底层实现
(1)跳跃表(Sorted Set实现)
跳跃表通过多层索引来模拟平衡树,实现快速的数据检索。其技术实现细节如下:
- 多级索引:跳跃表包含多层索引,每层索引都包含部分数据,通过比较值来决定是否前进。
- 随机化:在构建跳跃表时,随机选择索引点,以避免热点问题。
- 索引维护:通过插入和删除操作来维护跳跃表的索引。
(2)压缩列表(List/Hash优化存储)
压缩列表通过将多个元素紧凑地存储在连续的内存块中来优化List和Hash的存储。其技术实现细节如下:
- 元素编码:根据元素类型和大小,使用不同的编码方式来存储。
- 内存分配:在压缩列表中,内存分配是连续的,减少了内存碎片。
- 空间效率:通过压缩存储,减少了内存的使用。
(3)快速列表(QuickList)
快速列表结合了链表和数组的优点,用于存储列表数据结构。其技术实现细节如下:
- 分块存储:将链表分为多个块,每个块包含一定数量的元素。
- 内存分配:块之间是连续的,减少了内存碎片。
- 动态调整:根据链表的大小动态调整块的大小,以优化内存使用。
二、持久化机制
Redis提供了RDB和AOF两种持久化机制,以确保数据的安全。
1. RDB
(1)快照触发条件
RDB通过创建数据集的快照来保存数据,其触发条件包括:
- 手动触发:通过执行
SAVE
或BGSAVE
命令手动触发。 - 周期性触发:通过配置文件中的
save
指令,设置一定时间间隔自动触发。
(2)COW(写时复制)机制
RDB使用写时复制机制,即在创建快照时,对数据进行复制,从而避免在快照过程中对数据的修改。其技术实现细节如下:
- 数据复制:在创建快照时,将数据复制到一个新的内存区域。
- 数据更新:在快照过程中,所有对数据的更新都记录到一个临时文件中。
- 合并数据:快照完成后,将临时文件中的更新应用到快照数据中。
2. AOF
(1)重写压缩流程
AOF记录每次写操作的日志,为了防止日志文件过大,Redis提供了AOF重写功能。其技术实现细节如下:
- 重复写操作合并:将多个相同的写操作合并成一个,减少日志文件的大小。
- 压缩日志:通过压缩算法压缩日志文件,进一步减小文件大小。
(2)fsync策略(always/everysec/no)
fsync策略决定了Redis将数据同步到磁盘的频率。其技术实现细节如下:
- always:每次写操作都同步,保证数据不丢失,但性能较低。
- everysec:每秒同步一次,平衡了性能和数据安全性。
- no:不同步,性能最高,但数据安全性最低。
三、高可用方案
Redis提供了哨兵模式和集群模式两种高可用方案,以确保系统的稳定性和可靠性。
1. 哨兵模式
(1)主观/客观下线判定
哨兵通过主观和客观下线判定机制来判断Redis实例是否正常工作。其技术实现细节如下:
- 主观下线:哨兵通过ping命令来检测主节点是否响应,如果连续多次无响应,则认为主节点主观下线。
- 客观下线:哨兵之间通过通信来确认主节点是否客观下线,需要多数哨兵同意。
(2)领导者选举流程
当哨兵发现一个主节点下线时,会进行领导者选举,以选择一个新的主节点。其技术实现细节如下:
- 选举触发:哨兵发现主节点下线后,触发选举。
- 选举流程:哨兵之间通过投票来确定新的领导者。
(3)故障转移时序控制
在故障转移过程中,哨兵负责控制时序,确保数据的一致性。其技术实现细节如下:
- 故障检测:哨兵检测到主节点故障后,通知从节点。
- 数据复制:从节点复制主节点的数据。
- 角色切换:从节点成为新的主节点,原主节点成为从节点。
2. 集群模式
(1)哈希槽分配算法
集群模式将数据分配到不同的节点,每个节点负责一部分哈希槽。其技术实现细节如下:
- 哈希槽:数据通过哈希函数映射到哈希槽,每个槽由一个节点负责。
- 数据分布:通过哈希槽,将数据均匀地分布在不同的节点上。
(2)ASK/MOVED重定向
当客户端请求的数据不在当前节点时,Redis会返回ASK或MOVED重定向,引导客户端到正确的节点。其技术实现细节如下:
- ASK重定向:客户端需要将数据复制到另一个节点。
- MOVED重定向:客户端可以直接访问数据所在的节点。
(3)Gossip协议通信
集群节点之间通过Gossip协议进行通信,以同步状态和共享信息。其技术实现细节如下:
- Gossip消息:节点之间通过发送Gossip消息来交换信息。
- 状态同步:通过Gossip消息同步节点的状态。
- 信息共享:通过Gossip消息共享集群信息。
四、高级特性
Redis的高级特性包括内存管理、事务控制等,以下是对这些特性的详细解释:
1. 内存管理
(1)LRU/LFU淘汰策略
Redis使用LRU(最近最少使用)和LFU(最少使用频率)策略来淘汰内存中的数据。其技术实现细节如下:
- LRU:记录每个键的使用时间,当内存不足时,淘汰最久未使用的键。
- LFU:记录每个键的使用频率,当内存不足时,淘汰使用频率最低的键。
(2)内存碎片整理
Redis定期进行内存碎片整理,以提高内存利用率。其技术实现细节如下:
- 内存碎片:由于内存分配和释放操作,内存中可能会出现碎片。
- 碎片整理:通过移动内存中的数据,消除碎片,提高内存利用率。
(3)惰性删除机制
Redis在删除键时,不是立即释放内存,而是等待内存达到一定阈值时再进行释放。其技术实现细节如下:
- 阈值:当内存使用达到一定阈值时,触发内存释放操作。
- 延迟释放:延迟释放内存,以减少释放操作的频率。
2. 事务控制
(1)WATCH/MULTI/EXEC
Redis事务通过WATCH/MULTI/EXEC命令实现。其技术实现细节如下:
- WATCH:监控键值变化,如果键值在事务执行过程中被修改,则事务失败。
- MULTI:开启事务,将后续命令放入事务队列中。
- EXEC:执行事务队列中的命令。
(2)悲观锁实现
Redis可以通过SETNX命令实现悲观锁。其技术实现细节如下:
- SETNX:如果键不存在,则设置键的值。
- 锁:通过SETNX命令实现锁的功能,防止并发访问。
(3)Lua脚本原子性
Redis支持Lua脚本,并保证Lua脚本的原子性执行。其技术实现细节如下:
- 原子性:Lua脚本在执行过程中,不会被其他命令中断。
- 隔离性:Lua脚本执行期间,其他客户端无法访问Redis。
五、扩展组件
Redis的扩展组件包括Redis模块和生态工具,以下是对这些组件的详细介绍:
1. Redis模块
Redis模块允许用户扩展Redis的功能,例如RediSearch、RedisGraph和RedisTimeSeries等。其技术实现细节如下:
- 模块开发:用户可以开发自己的Redis模块,通过C语言编写。
- 模块安装:将模块编译成.so文件,并加载到Redis中。
- 模块功能:模块可以提供新的数据结构、命令和功能。
2. 生态工具
(1)RedisInsight(可视化监控)
RedisInsight是一个可视化监控工具,用于监控Redis的性能和状态。其技术实现细节如下:
- 性能监控:监控Redis的性能指标,如内存使用、连接数等。
- 状态监控:监控Redis的状态信息,如集群状态、哨兵状态等。
- 可视化界面:提供直观的界面来展示监控数据。
(2)RedisBloom(布隆过滤器)
RedisBloom是一个布隆过滤器实现,用于快速判断元素是否存在于集合中。其技术实现细节如下:
- 布隆过滤器:布隆过滤器是一种空间效率非常高的概率数据结构,用于快速判断元素是否存在。
- 概率性:布隆过滤器可能会误判,但不会漏判。
- 应用场景:适用于需要快速判断元素是否存在,且对误判容忍度较高的场景。
(3)twemproxy(分片代理)
twemproxy是一个分片代理,可以将请求分发到不同的Redis节点。其技术实现细节如下:
- 分片:将数据分布到不同的Redis节点上。
- 代理:twemproxy作为代理,将客户端请求分发到对应的Redis节点。
- 负载均衡:twemproxy可以实现负载均衡,提高系统的性能和可用性。
六、性能优化
Redis的性能优化包括客户端和服务端两个方面,以下是对这些优化的详细介绍:
1. 客户端
(1)Pipeline批处理
Pipeline允许客户端将多个命令打包成一个批量请求,从而减少网络延迟。其技术实现细节如下:
- 批量请求:将多个命令打包成一个批量请求,减少网络请求的次数。
- 减少延迟:通过批量请求,减少网络延迟,提高性能。
(2)连接池配置
合理配置连接池大小,可以提高客户端的性能。其技术实现细节如下:
- 连接池:连接池可以复用连接,减少连接建立和销毁的开销。
- 连接数量:根据应用场景和性能需求,合理配置连接池的大小。
(3)读写分离策略
读写分离可以将读操作和写操作分配到不同的节点,从而提高性能。其技术实现细节如下:
- 读分离:将读操作分配到从节点,减少主节点的压力。
- 写操作:将写操作分配到主节点,保证数据的一致性。
2. 服务端
(1)多IO线程
Redis使用多IO线程来处理网络请求,从而提高并发性能。其技术实现细节如下:
- IO线程:Redis使用多IO线程来处理网络请求,提高并发处理能力。
- 线程池:使用线程池来管理IO线程,减少线程创建和销毁的开销。
(2)后台线程优化
Redis的后台线程负责数据持久化和内存淘汰等任务,优化这些线程可以提高性能。其技术实现细节如下:
- 数据持久化:后台线程负责将数据持久化到磁盘,保证数据的安全性。
- 内存淘汰:后台线程负责淘汰内存中的数据,提高内存利用率。
(3)大key拆分方案
对于大key,可以通过拆分来降低内存占用,提高性能。其技术实现细节如下:
- 大key:大key占用内存较多,对性能有较大影响。
- 拆分:将大key拆分成多个小key,降低内存占用。
总结
Redis作为一款高性能的键值数据库,其核心数据结构、持久化机制、高可用方案、高级特性、扩展组件和性能优化等方面都具有很高的专业性。通过深入了解这些知识点,我们可以更好地利用Redis的优势,为应用程序提供高性能、高可靠性的数据存储解决方案。
📥博主的人生感悟和目标

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

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