天下武功,无坚不摧,唯快不破!我的名字叫 Redis,全称是 Remote Dictionary Server。
有人说,组 CP,除了要了解她外,还要给机会让她了解你。
那么,作为开发工程师的你,是否愿意认真阅读此心法抓住机会来了解我,运用到你的系统中提升性能。
我遵守 BSD 协议,由意大利人 Salvatore Sanfilippo 使用 C 语言编写的一个基于内存实现的键值型非关系(NoSQL)数据库。
我是一个内存数据结构存储、可作为数据库、缓存、消息队列、流处理引擎,速度快是我的特点。
根据官方数据,Redis 的 QPS 可以达到约 100000(每秒请求数)。
我提供了 String(字符串)、Hashes(散列表)、Lists(列表)、Sets(无序集合)、Sorted Sets(可根据范围查询的排序集合)、Bitmap(位图)、HyperLogLog、Geospatial (地理空间)和 Stream(流)等数据结构。
数据结构的使用技法和实现原理是你核心筑基必经之路,好好修炼。
除此之外,我还具有主从复制、Lua 脚本、LRU 淘汰机制,事务和不同级别的磁盘持久化功能,并通过 Redis Sentinel(哨兵)和 Redis Cluster(Redis 集群)实现高可用,这部分内容,重中之重,高手必备。
我还支持一些原子操作,支持异步复制实现快速非阻塞同步和自动重连,另外需要注意的是,推荐你在 Lunix /Unix 系统上部署,官方并没有在 Windows 系统上构建安装包。
程许媛:“Redis 你说了这么多?你能干啥?别王婆卖瓜,自卖自夸。”
缓存
这是我被使用的最多的场景,能极大提升应用程序的性能。当单个 MySQL 读写压力比较大,场景是读多写少的时候,把热点数据存储在更快的存储中,也就是 Redis。
读取数据
先从缓存中读取数据是否命中。
缓存未命中,则查询数据库获取数据,并把数据写到 Redis 中,让后续读取相同数据的请求命中缓存,最后把数据返回给调用者。
缓存命中,直接返回。
写数据
至于修改数据,程序员想了很多方法去尽可能保证 Redis 与 MySQL 的数据一致性。
先写 MySQL 数据,再删除 Redis 缓存数据。
监听 MySQL binlog 日志,修改 Redis 数据。
排行榜
使用 MySQL 等关系型数据库,非常麻烦,性能也差,而直接使用 Redis SortedSet 轻松搞定。
消息队列
简单消息队列,在一些不需要高可靠,但是数据量大会给 MySQL 带来非常大压力的场景,比如:到货通知、未读消息、邮件发送之列的。程序员可以使用 Lists 来实现一个队列。
分布式锁
Redisson 这个框架,就是使用 Redis 弄出了一套分布式锁解决方案。
计数器
Redis 的命令都是原子性的,程序员可以轻松地利用 INCR
,DECR
命令来构建计数器系统。
还有很多场景,我会在后面章节详细道来,学完之后,我相信你定能筑基锻体,念头通达,升职加薪。
千古无同局,叶底能否藏花,我们未来印证,愿此心法能让你学有所成,你来,我等着。
经过上一篇的 Redis 简介,我相信你一定想继续了解 Redis。本章节会通过源代码编译来安装 Redis 7.0.5,让你在自己的机器上搭建一套可以 Debug 的 Redis 7.0.5 源码环境。
这也是后续原理分析的基础,推荐你部署在 macOS 或者 Linux 上搭建,如果你是 Windows 环境,那就搞一个虚拟机在上面装一个 Linux 系统,再继续搭建 Redis 环境。
程许媛:“我的电脑是 Mac OS 系统,你就用这个来演示吧。”
有两种方式,第一种是从官网下载 Redis 源码压缩包,如图 1-1 所示。
图1-1
图 1-1
将压缩包解压得到一个文件夹。
第二种方式,通过 git clone 获取源码。
从 Github 上,使用 git clone https://github.com/redis/redis.git
指令下载,下载完成后你会得到如下文件。
图 1-2
图 1-2
进入 redis 目录,使用 git checkout
切换到 7.0.5 这个 tag 。
gir checkout tags/7.0.5 -b 7.0.5
在编译之前,需要安装一些环境依赖,Redis 是 C 语言编写的,所以还需要 gcc 编译器。
执行 gcc -v
判断是否安装了编译器。
图 1-3
图 1-3
没有安装的话,使用如下指令安装。
xcode-select --install
一切准备就绪,进入 redis 的源码目录,执行 make
命令就可以了,你可以类比成 Java 中的 mvn 命令。
make CFLAGS="-g -O0" MALLOC=jemalloc
命令后边的 “-O0” 参数表示告诉编译器不要优化代码,防止你在 Debug 的时候, IDE 里面的 Redis 源码与实际运行的代码对应不上。
MALLOC=jemalloc
,指定在 Mac OS 系统上 Redis 使用 jemalloc 内存分配器,Linux 默认使用该分配器,如果是 Linux 系统,无需指定该参数。
内存碎片自动清理功能只在 jemalloc 内存分配器生效,所以才加上这个参数指定内存分配器。
如果在 Linux 系统上用于生产环境,那么直接使用指令 make
命令即可。
编译成功,将会看到图 1-4 中Hint: It's a good idea to run 'make test' ;)
,提示我们可以运行单元测试,这一步可以省略。
图 1-4
图 1-4
编译成功,进入 src 源码目录下,你会看到一个 redis-server 的可执行程序,使用如下指令启动。
./redis-server ../redis.conf
图 1-5
图 1-5
编译好了,我们还差一个方便阅读和调试源码的工具。为了方便阅读和 debug 源码,极力推荐你使用 CLion 来阅读和调试 Redis 源码,我使用的是 CLion 2021.3 版本,它支持 Makefile 的项目。
安装好以后,打开 CLion,点击 open,选择 Redis 源码目录即可。
图 1-6
图 1-6
之后检查下 Run Debug 是否出现这些选项,选择编辑。
图 1-7
图 1-7
选择编辑 redis-server ,指定启动配置文件 redis.conf
的目录,保存。
图 1-8
图 1-8
在 server.c
的main()
方法加断点,Debug 启动 redis -server,进行源码 Debug。
图 1-9
图 1-9
大功告成,接下来就可以在 Redis 的知识海洋里呛水了。
在知识海洋呛水之前,先来了解下 Redis 的目录结构,从 Redis 整体目录结构来对系统有个全局的认识,了解一个系统的主要组成,同时防止陷入细节或者无从下手。
deps
这个目录主要包含 Redis 所依赖的第三方代码库。
Jemalloc,内存分配器,默认情况下选择该内存分配器来代替 Linux 系统的 libc-malloc,libc-malloc 性能不高,且碎片化严重。
hiredis,这是官方 C 语言客户端。
linenoise 是一种读线替换。它由 Redis 的 同一作者开发,但作为一个单独的项目进行管理,并根据需要进行更新。
lua,顾名思义,就是 lua 相关的功能。
hdr_histogram,用于生成每个命令的延迟跟踪直方图。
src 目录
这是 Redis 源码的重要组成部分,里面有 commands
和 modules
两个子目录,其余功能模块的源码都在 src 目录下,这是最重要的目录。
modules
目录包含了实现Redis module
的示例代码,commands
里面都是 json 格式的文件,包含了每个指令的元信息。
tests 目录
顾名思义,功能模块测试和单元测试的代码就在这里。
cluster,Redis Cluster 功能测试。
sentinel,哨兵集群功能测试。
unit,单元测试。
integration,主从复制功能测试。
剩下的 assets、helpers、modules、support 四个目录中是用来支撑测试功能的。
utils 目录
辅助性功能的脚本或者代码,比如用于创建 Redis Cluster 的脚本,lru 算法效果展示代码等。
除此之外,Redis 源码目录还有两个重要的文件,redis.conf 和 sentinel.conf,分别用于配置 Redis 实例运行和哨兵配置。