带你读《Redis 5设计与源码分析》之一:引  言

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 本书从底层源码的角度,对 Redis的数据结构以及持久化、主从复制、哨兵和集群等特性的实现原理进行了详尽的剖析,图文并茂。

数据库技术丛书
点击查看第二章
点击查看第三章
Redis 5设计与源码分析
image.png
陈雷 等编著

第1章

引  言

Redis是目前最流行的键值对(key-value)数据库,以出色的性能著称,官方提供的数据是可以支持100 000以上的+QPS。Redis具有高性能的主要原因如下。
1)Redis是基于内存的存储数据库,绝大部分的命令处理只是纯粹的内存操作,内存的读写速度非常快。
2)Redis是单进程线程的服务(实际上一个正在运行的Redis Server肯定不止一个线程,但只有一个线程来处理网络请求),避免了不必要的上下文切换,同时不存在加锁/释放锁等同步操作。
3)Redis使用多路I/O复用模型(select、poll、epoll),可以高效处理大量并发连接。
4)Redis中的数据结构是专门设计的,增、删、改、查等操作相对简单。
本章主要介绍Redis简介、Redis 5.0的新特性、Redis源代码概念、Redis安装与调试,希望对读者阅读和研究Redis源码有一定的帮助。

1.1 Redis简介

Redis(REmote DIctionary Server)是一个使用ANSI C编写的、开源的、支持网络的、基于内存的、可选持久化的键值对存储系统。在2013年5月之前,Redis的开发由VMware赞助;2013年5月至2015年6月,由Pivotal赞助;从2015年6月起,Redis的开发由Redis Labs赞助。根据数据库使用排行网站db-engines.com上的排名,Redis是目前最流行的键值对存储系统。
Redis由Salvatore Sanfilippo在2009年发布初始版本,开源后不断发展壮大,目前的最新版为Redis 5.0。Redis的主要版本如下。
1)2009年5月发布Redis初始版本。
2)2012年发布Redis 2.6.0。
3)2013年11月发布Redis 2.8.0。
4)2015年4月发布Redis 3.0.0,该版本引入了集群。
5)2017年7月发布Redis 4.0.0,该版本引入了模块系统。
6)2018年10月发布Redis 5.0.0,该版本引入了Streams结构。
Redis在互联网数据存储方面应用广泛,主要具有以下优点。
1)Redis是内存型的数据库,也就是说Redis中的key-value对是存储在内存中的,因而效率比磁盘型的快。
2)Redis的工作模式为单线程,不需要线程间的同步操作。Redis采用单线程主要因为其瓶颈在内存和带宽上,而不是CPU。
3)Redis中key-value的value不仅可以是字符串,也可以是复杂的数据类型,如链表、集合、散列表等。
4)Redis支持数据持久化,可以采用RDB、AOF、RDB&AOF三种方案。计算机重启后可以在磁盘中进行数据恢复。
5)Redis支持主从结构,可以利用从实例进行数据备份。

1.2 Redis 5.0的新特性

相较于Redis 4.0,Redis 5.0增加了很多新的特性,限于篇幅,本节主要介绍几个较重要的特性,具体内容可以参考官方文档。
1)新增Streams数据类型,这是Redis 5.0最重要的改进之一。可以把Streams当作消息队列,详细内容参见后续章节。
2)新的模块API、定时器、集群及字典。
3)RDB中持久化存储LFU和LRU的信息。
4)将集群管理功能完全用C语言集成到redis-cli中,Redis 3.x和Redis 4.x的集群管理是通过Ruby脚本实现的。
5)有序集合新增命令ZPOPMIN/ZPOPMAX。
6)改进HyperLogLog的实现。
7)新增Client Unblock和Client ID。
8)新增LOLWUT命令。
9)Redis主从复制中的从不再称为Slave,改称Replicas。
10)Redis 5.0引入动态哈希,以平衡CPU的使用率和相应性能,可以通过配置文件进行配置。Redis 5.0默认使用动态哈希。
11)Redis核心代码进行了部分重构和优化。

1.3 Redis源码概述

Redis源代码主要存放在src文件夹中,作者没有整理这些文件,统一存放到了一个文件夹中,如图1-1所示。其中server.c为服务端程序,redis-cli.c为客户端程序。
image.png
Redis源代码的核心部分主要如下。
(1)基本的数据结构

  • 动态字符串sds.c
  • 整数集合intset.c
  • 压缩列表ziplist.c
  • 快速链表quicklist.c
  • 字典dict.c
  • Streams的底层实现结构listpack.c和rax.c

(2)Redis数据类型的底层实现

  • Redis对象object.c
  • 字符串t_string.c
  • 列表t_list.c
  • 字典t_hash.c
  • 集合及有序集合t_set.c和t_zset.c
  • 数据流t_stream.c

(3)Redis数据库的实现

  • 数据库的底层实现db.c
  • 持久化rdb.c和aof.c

(4)Redis服务端和客户端实现

  • 事件驱动ae.c和ae_epoll.c
  • 网络连接anet.c和networking.c
  • 服务端程序server.c
  • 客户端程序redis-cli.c

(5)其他

  • 主从复制replication.c
  • 哨兵sentinel.c
  • 集群cluster.c
  • 其他数据结构,如hyperloglog.c、geo.c等
  • 其他功能,如pub/sub、Lua脚本

以上为Redis核心代码的简单划分,本书重点介绍Redis客户端使用命令的底层实现,在阅读后续章节时,建议按照本书编排顺序进行阅读。首先学习Redis底层的数据存储结构;然后学习Redis每个命令的具体实现;最后可以根据需要学习Redis其他方面的内容,如主从复制、哨兵、集群、持久化等。

1.4 Redis安装与调试

我们以 Linux 环境为例来进行安装。
通过网址http://download.redis.io/releases/ 可以获得各个版本的Redis源码,本书以Redis 5.0为例,下载源码包并编译安装(源码包URL为http://download.redis.io/releases/redis-5.0.0.tar.gz) 。
$ wget http://download.redis.io/releases/redis-5.0.0.tar.gz
$ tar -zxvf redis-5.0.0.tar.gz
$ cd redis-5.0.0
$ make
$ cd src
$make install
到此,我们完成了Redis 5.0的编译安装,生成的可执行文件在/usr/local/bin目录中:
redis-benchmark redis-check-aof redis-check-rdb redis-cli
redis-sentinel redis-server
其中redis-benchmark是官方自带的Redis性能测试工具;当AOF文件或者RDB文件出现语法错误时,可以使用redis-check-aof或者redis-check-rdb修复;redis-cli是客户端命令行工具,可以通过命令redis-cli -h {host} -p {port}连接到指定Redis服务器;redis-sentinel是Redis哨兵启动程序;redis-server是Redis服务端启动程序。
例如,使用redis-server启动服务端程序(默认监听端口是6379):
$ /usr/local/bin/redis-server
使用redis-cli连接Redis服务器并添加键值对:
$ redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> get name
"zhangsan"
GDB是一个由GNU开源组织发布的、UNIX/Linux操作系统下的、基于命令行的、功能强大的程序调试工具。下面我们演示如何通过GDB来调试Redis。
用GDB启动redis-server服务端程序:
$ gdb /usr/local/bin/redis-server
(gdb)
使用b命令在main函数入口增加断点:
(gdb) b main
Breakpoint 1 at 0x427770: file server.c, line 4000.
使用r命令运行:
(gdb) r
Starting program: /usr/local/bin/redis-server
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".

Breakpoint 1, main (argc=1, argv=0x7fffffffe528) at server.c:4000
4000 int main(int argc, char **argv)
从上面的输出中可以看到,代码执行到main函数停止。接下来,使用n命令执行下一步:
(gdb) n
4034 spt_init(argc, argv);
使用p命令查看某个变量的信息:
(gdb) p argc
$1 = 1
这里只是简要介绍使用GDB调试Redis程序的方法,更多GDB的使用技巧有待读者去研究。
当然,还可使用很多方便的源码阅读工具阅读代码。例如,Windows环境下有一款功能强大的IDE(集成开发环境)—Source Insight,内置C++代码分析功能;同时能自动维护项目内的符号数据库,非常方便。另外,Mac 平台下功能强大的 IDE(集成开发环境)—Understand具备代码依赖、图形化等实用功能。Linux环境下可以使用 Vim + Ctags 来阅读代码,其中Ctags 是Vim下阅读代码的一个辅助工具,可以生成函数、类、结构体、宏等语法结构的索引文件,使用方法也非常简单。读者可以自行学习这些源码阅读工具的具体安装教程,这里不再赘述。

1.5 本章小结

本章首先介绍了Redis的发展历程及Redis 5.0的新特性。然后重点讲解了如何阅读Redis源代码,并简单介绍了Redis源码的安装与调试方法,为读者学习后续章节奠定基础。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
4月前
|
消息中间件 存储 NoSQL
Redis数据结构—跳跃表 skiplist 实现源码分析
Redis 是一个内存中的数据结构服务器,使用跳跃表(skiplist)来实现有序集合。跳跃表是一种概率型数据结构,支持平均 O(logN) 查找复杂度,它通过多层链表加速查找,同时保持有序性。节点高度随机生成,最大为 32 层,以平衡查找速度和空间效率。跳跃表在 Redis 中用于插入、删除和按范围查询元素,其内部节点包含对象、分值、后退指针和多个前向指针。Redis 源码中的 `t_zset.c` 文件包含了跳跃表的具体实现细节。
|
6月前
|
NoSQL 算法 Redis
Redis系列-11.RedLock算法和底层源码分析
Redis系列-11.RedLock算法和底层源码分析
113 0
|
6月前
|
存储 NoSQL 关系型数据库
Redis持久化策略AOF、RDB详解及源码分析
Redis持久化策略AOF、RDB详解及源码分析
|
6月前
|
存储 NoSQL 算法
Redis源码分析-存储原理与数据模型
Redis源码分析-存储原理与数据模型
98 0
|
NoSQL 安全 API
redis6.0源码分析:简单动态字符串sds
redis6.0源码分析:简单动态字符串sds
51 0
redis6.0源码分析:简单动态字符串sds
|
存储 NoSQL 算法
redis6.0源码分析:跳表skiplist
redis6.0源码分析:跳表skiplist
59 0
|
NoSQL 安全 算法
redis6.0源码分析:字典扩容与渐进式rehash
redis6.0源码分析:字典扩容与渐进式rehash
198 0
|
NoSQL Redis
从源码分析Redis分布式锁的原子性保证(二)
从源码分析Redis分布式锁的原子性保证
132 0
|
移动开发 NoSQL Redis
从源码分析Redis分布式锁的原子性保证(一)
从源码分析Redis分布式锁的原子性保证
222 0
|
NoSQL 算法 Java
Redis进阶-JedisCluster初始化 & 自动管理连接池中的连接 _ 源码分析
Redis进阶-JedisCluster初始化 & 自动管理连接池中的连接 _ 源码分析
604 0