本书深入地分析了Redis核心功能的内部机制与实现方式,大部分内容源自对Redis源码的分析,并从中总结出实现原理。通过阅读本书,读者可以快速、轻松地了解Redis的内部运行机制。
本书首先介绍了Redis常用的数据类型的编码格式,包括字符串、列表、散列、集合、有序集合,这是Redis存储数据的基础。接着分析了Redis的事件机制,剖析了Redis事件驱动的实现原理,通过这部分内容,读者可以了解一个远程服务程序的整体架构。本书还分析了Redis持久化、主从复制、Sentinel机制、Cluster机制的实现原理,这部分内容是Redis的核心功能。在这部分内容中,本书也会延伸分析Redis中使用的UNIX机制,如UNIX网络编程、进程通信、线程同步等,并通过Redis源码展示这些UNIX机制的使用方式。
本书最后介绍了Redis的高级特性,包括事务、非阻塞删除、Lua脚本、Module模块、Stream消息流,以及Redis 6提供的ACL访问控制列表、Tracking机制等,这部分内容不仅分析内部实现,还提供了详细的使用案例,帮助读者循序渐进地了解这些特性。
深入分析Redis核心功能的内部机制与实现方式;
本书还分析了Redis持久化、主从复制、Sentinel机制、Cluster机制的实现原理;
延伸分析Redis中使用的UNIX机制,如UNIX网络编程、进程通信、线程同步等,并通过Redis源码展示这些UNIX机制的使用方式。
本书适合对Redis感兴趣或者想深入了解Redis实现机制的读者。
前 言
Redis是开源的key-value存储系统,可作为数据库、缓存、消息组件。Redis的作者是Salvatore Sanfilippo(网名为antirez),他在2009年开发完成并开源了Redis。Redis由于性能极高、功能强大,迅速在业界流行,现已成为高并发系统中最常用的组件之一。
Redis提供了多种类型的数据结构,如字符串(String)、散列(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)等。Redis还是分布式系统,主从集群可以实现数据热备份,哨兵(Sentinel)机制可以保证主从集群高可用,Cluster集群则提供了水平扩展的能力。Redis还提供了持久化、Lua脚本、Module模块、Stream消息流、Tracking机制等一系统强大功能,适用于各种业务场景。
写作目的
虽然笔者主要使用Java语言开发程序,却一直希望从源码层面深入分析一个C语言实现的分布式系统。C语言可以说是最接近低级语言的开发语言,分析C语言程序,可以让我们更深入地理解操作系统的底层知识。于是,笔者学习了Redis源码,并编写了本书。
为什么选择Redis呢?因为Redis是一个典型的“小而美”的程序。Redis实现简单,源码非常优雅简洁,阅读起来并不吃力,而且Redis功能齐全,涵盖了数据存储、分布式、消息流等众多特性,非常值得深入学习。
通过编写本书,笔者对Redis、UNIX编程、分布式系统、存储系统都有了更深入的理解,再学习其他相关的系统(如MySQL、Nginx等),就可以举一反三、触类旁通。希望本书也可以帮助读者百尺竿头,更进一步。
本书特点
本书深入分析了Redis的实现原理,所以并不是Redis的入门书。为了尽量降低阅读难度,本书总结了Redis各个核心功能的实现原理,提取了Redis核心代码(本书会尽量避免堆积代码),并以适量图文,对Redis源码及其实现原理进行详细分析,向读者展示Redis核心功能的设计思想和实现流程。
虽然本书的大部分内容基于对Redis源码的分析,但是并不复杂,即使读者只是简单了解C语言的基础语法,也可以轻松读懂。
另外,本书结合Redis目前的最新版本6.0.9,分析了Redis最新特性,如Redis 6的ACL、Tracking等机制。为了照顾对Redis最新特性不熟悉的读者,这部分内容提供了详细的应用示例,帮助读者循序渐进、由浅到深地学习和理解Redis最新特性。
本书也不局限于Redis,而是由Redis延展出了两方面内容:
(1)Redis中使用的UNIX机制,包括UNIX网络编程、线程同步等内容,本书会通过源码展示Redis如何使用这些UNIX机制。
(2)如何通过Redis实现一个分布式系统,主要是Sentinel、Cluster机制的实现原理。
本书使用的源码版本是Redis 6.0.9,本书提供的Redis操作案例,如无特殊说明,也是在Redis 6.0.9版本上执行的操作实例。
本书结构
第1部分分析了Redis的字符串、列表、散列、集合这几种数据类型的编码格式。编码格式,即数据的存储格式,对于数据库,数据的存储格式至关重要,如关系型数据库的行式存储和列式存储。而Redis作为内存数据库,对于数据编码的总体设计思想是:最大限度地“以时间换空间”,从而最大限度地节省内存。这部分内容详细分析了Redis对内存的使用如何达到“锱铢必较”的程度。
第2部分分析了Redis的核心流程,包括Redis事件机制与命令执行过程。Redis利用I/O复用模型,实现了自己的事件循环机制,而Redis底层由该事件机制驱动运行(很多远程服务程序都使用类似的架构,如Nginx、MySQL等)。Redis事件机制设计优雅、实现简单,并且性能卓越,可以说是“化繁为简”。
第3部分分析了Redis持久化与复制机制。虽然Redis是内存数据库,但仍然最大限度地保证了数据的可靠性。不管是文件持久化,还是从节点复制,核心思想都是一样的:通过将数据复制到不同备份中,从而保持数据安全。这部分内容分析了RDB、AOF持久化机制,以及主从节点复制流程等内容,向读者展示了Redis数据是如何“不胫而走”的。
第4部分分析了Redis分布式架构。这部分内容从流行的分布式算法Raft出发,分析了Sentienl如何监控节点,Cluster集群如何实现数据分片,如何支持动态新增、删除集群节点,以及它们的“拿手好戏”——故障转移。分布式系统常常让笔者想到一个有趣的词—铁索连舟(将集群节点想象为“舟”,将节点之间的网络连接想象为“索”)。
第5部分分析了Redis中的高级特性,包括Redis事务、非阻塞删除、ACL访问控制列表、Tracking机制、Lua脚本、Module模块、Stream消息流等内容。Redis为各种高性能、高可用场景提供了非常全面的支持,可以说是“包罗万象”。
本书不是Redis工具书,并没有将Redis的全部功能都分析一遍,很多功能也非常有趣实用,但本书不会深入讨论,如Bitmaps、Hyperloglog、Geo、Pub/Sub等,读者可以自行深入学习。
表达约定
(1)本书会按顺序在源码函数(或代码块)中添加标志,并在源码展示结束后,按标志对源码进行说明,例如:
robj *tryObjectEncoding(robj *o) {
...
// [1]
if (o->refcount > 1) return o;
...
}
【1】该redisObject被多处引用,不再进行编码操作,以免影响他处的使用,直接退出函数。
这样可以保证源码展示的整洁,也方便读者阅读源码后,再结合书中说明,深入理解。
另外,也方便读者在阅读本书时,结合阅读完整的Redis源码。
在源码中使用“...”代表此处省略了代码(有些地方省略了日志等辅助的代码,可能不添加“...”标志)。
(2)如果源码中函数太长,为了版面整洁,本书将其划分为多个代码段,并使用“// more”标志该函数后续还有其他代码段,请读者留意该标志。
勘误和支持
在阅读本书的过程中有任何问题或者建议,可以关注公众号(binecy)与笔者交流。笔者十分感谢并重视您的反馈,会对您提出的问题、建议进行梳理与反馈,并在本书后续版本中及时做出勘误与更新。
致谢
感谢写作过程中身边朋友的支持,他们给予笔者很多的力量。
感谢Redis的作者antirez,优秀的Redis离不开antirez的辛勤付出,向他致敬。
感谢电子工业出版社博文视点的陈晓猛编辑,陈编辑专业的写作指导和出版组织工作,使得本书得以顺利出版。
感谢计算机行业的内容创作者,他们的各种分享、博客文章及图书都在积极推动行业的发展,也为本书的编写提供了灵感和参考。
梁国斌