You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
13 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 开篇词 | 这样学Redis才能技高一筹
你好我是蒋德钧欢迎和我一起学习Redis。
我博士毕业后就一直在中科院计算所工作现在的职位是副研究员。在过去的14年时间里我一直从事互联网底层基础设施方面的研究工作主要的研究方向为新型存储介质、键值数据库、存储系统和操作系统。
2015年的时候我和我的团队接到了一个高难度任务目标是设计一个单机性能达到千万级吞吐量的键值数据库。为了实现这个目标我们就开始重点研究Redis从此我就和这个数据库结缘了。
作为键值数据库Redis的应用非常广泛如果你是后端工程师我猜你出去面试八成都会被问到与它相关的性能问题。比如说为了保证数据的可靠性Redis需要在磁盘上读写AOF和RDB但在高并发场景里这就会直接带来两个新问题一个是写AOF和RDB会造成Redis性能抖动另一个是Redis集群数据同步和实例恢复时读RDB比较慢限制了同步和恢复速度。
那这个问题有没有好的解决方法呢哈哈这里我卖了个关子。其实一个可行的解决方案就是使用非易失内存NVM因为它既能保证高速的读写又能快速持久化数据。我和团队就在NVM的键值数据库上开展了诸多深入研究先后申请了二十余项专利也在顶级学术会议上发表了学术论文。
当然这些研究最后都是为了完成一开始说的那个大目标设计一个单机千万级吞吐量的键值数据库。在这个过程中我也深入、透彻地研究了Redis包括它的源代码、架构设计以及核心控制点。
另外因为各大互联网公司在Redis应用方面比较超前场景比较丰富他们会遇到各种各样的棘手问题所以这几年我和蚂蚁金服、百度、华为、中兴等公司都有合作致力于和他们一起解决生产环境的各种疑难杂症。
最后对标Redis我们团队也研发了高性能键值数据库[HiKV](https://www.usenix.org/conference/atc17/technical-sessions/presentation/xia)等,你感兴趣的话,可以点开链接看看整体的设计。
正是因为有这样的研究和项目经历让我目睹了同样是使用Redis但是不同公司的“玩法”却不太一样比如说有做缓存的有做数据库的也有用做分布式锁的。不过他们遇见的“坑”总体来说集中在四个方面
* CPU使用上的“坑”例如数据结构的复杂度、跨CPU核的访问
* 内存使用上的“坑”例如主从同步和AOF的内存竞争
* 存储持久化上的“坑”例如在SSD上做快照的性能抖动
* 网络通信上的“坑”,例如多实例时的异常网络丢包。
随着这些深入的研究、实战操作、案例积累我拥有了一套从原理到实战的Redis知识总结。这一次我想把我多年积累的经验分享给你。
## 为什么懂得了一个个技术点却依然用不好Redis
我知道很多同学都是带着一个个具体的问题来学这门课的比如说Redis数据怎么做持久化集群方案应该怎么做这些问题当然很重要但是如果你只是急于解决这些细微的问题你的Redis使用能力就很难得到质的提升。
这些年,在和国内大厂的合作过程中,我发现,很多技术人都有一个误区,那就是,**只关注零散的技术点,没有建立起一套完整的知识框架,缺乏系统观,但是,系统观其实是至关重要的。**从某种程度上说,在解决问题时,拥有了系统观,就意味着你能有依据、有章法地定位和解决问题。
说到这儿,我想跟你分享一个小案例。
现在很多大厂的Redis服务面临的请求规模很大因此在评估性能时仅仅看平均延迟已经不够了。我简单举个例子假设Redis处理了100个请求99个请求的响应时间都是1s而有一个请求的响应时间是100s。那么如果看平均延迟这100个请求的平均延迟是1.99s但是对于这个响应时间是100s的请求而言它对应的用户体验将是非常糟糕的。如果有100万个请求哪怕只有1%的请求是100s这也对应了1万个糟糕的用户体验。这1%的请求延迟就属于长尾延迟。
我之前在做一个项目的时候要把Redis的长尾延迟维持在一定阈值以下。你可以想一下如果是你你会怎么做呢
刚开始的时候,我有些无从下手,因为那个时候,我并不清楚跟长尾延迟相关的东西都有哪些,只能一个个摸索。
首先我对Redis的线程模型做了分析我发现对于单线程的Redis而言任何阻塞性操作都会导致长尾延迟的产生。接着我又开始寻找可能导致阻塞的关键因素一开始想到的是网络阻塞但随着对Redis网络框架的理解我知道Redis网络IO使用了IO复用机制并不会阻塞在单个客户端上。
再后来我又把目光转向了键值对数据结构、持久化机制下的fork调用、主从库同步时的AOF重写以及缓冲区溢出等多个方面。绕了一大圈子之后这条影响长尾延迟的“证据链”才得以形成。这样一来我也系统地掌握了影响Redis性能的关键因素路径之后再碰到类似的问题时我就可以轻松解决了。
那么如何高效地形成系统观呢我们做事情一般都希望“多快好省”说白了就是希望花很少的时间掌握更丰富的知识和经验解决更多的问题。听起来好像很难但实际上只要你能抓住主线在自己的脑海中绘制一幅Redis全景知识图这完全是可以实现的。而这也是我在设计这门课时所遵循的思路。
那么所谓的Redis知识全景图都包括什么呢简单来说就是“两大维度三大主线”。
![](https://static001.geekbang.org/resource/image/79/e7/79da7093ed998a99d9abe91e610b74e7.jpg?wh=2001*1126)
“两大维度”就是指系统维度和应用维度,“三大主线”也就是指高性能、高可靠和高可扩展(可以简称为“三高”)。
首先从系统维度上说你需要了解Redis的各项关键技术的设计原理这些能够为你判断和推理问题打下坚实的基础而且你还能从中掌握一些优雅的系统设计规范例如run-to-complete模型、epoll网络模型这些可以应用到你后续的系统开发实践中。
这里有一个问题是Redis作为庞大的键值数据库可以说遍地都是知识一抓一大把我们怎么能快速地知道该学哪些呢别急接下来就要看“三大主线”的魔力了。
别看技术点是零碎的,其实你完全可以按照这三大主线,给它们分下类,就像图片中展示的那样,具体如下:
* **高性能主线**,包括线程模型、数据结构、持久化、网络框架;
* **高可靠主线**,包括主从复制、哨兵机制;
* **高可扩展主线**,包括数据分片、负载均衡。
你看,这样,你就有了一个结构化的知识体系。当你遇见这些问题时,就可以按图索骥,快速找到影响这些问题的关键因素,这是不是非常省时省力呢?
其次,在应用维度上,我建议你按照两种方式学习: “**应用场景驱动**”和“**典型案例驱动**”,一个是“面”的梳理,一个是“点”的掌握。
我们知道缓存和集群是Redis的两大广泛的应用场景。在这些场景中本身就具有一条显式的技术链。比如说提到缓存场景你肯定会想到缓存机制、缓存替换、缓存异常等一连串的问题。
不过并不是所有的东西都适合采用这种方式比如说Redis丰富的数据模型就导致它有很多零碎的应用场景很多很杂。而且还有一些问题隐藏得比较深只有特定的业务场景下比如亿级访问压力场景才会出现并不是普遍现象所以我们也比较难于梳理出结构化的体系。
这个时候你就可以用“典型案例驱动”的方式学习了。我们可以重点解读一些对Redis的“三高”特性影响较大的使用案例例如多家大厂在万亿级访问量和万亿级数据量的情况下对Redis的深度优化解读这些优化实践非常有助于你透彻地理解Redis。而且你还可以梳理一些方法论做成Checklist就像是一个个锦囊之后当你遇到问题的时候就可以随时拿出自己的“锦囊妙计”解决问题了。
最后我还想跟你分享一个非常好用的技巧。我梳理了一下这些年遇到的、看到的Redis各大典型问题同时结合相关的技术点手绘了一张Redis的问题画像图。无论你遇见什么问题都可以拿出来这张图这样你就能快速地按照问题来查找对应的Redis主线模块了然后再进一步定位到相应的技术点上。
![](https://static001.geekbang.org/resource/image/70/b4/70a5bc1ddc9e3579a2fcb8a5d44118b4.jpeg?wh=2048*1536)
举个例子如果你遇到了Redis的响应变慢问题对照着这张图你就可以发现这个问题和Redis的性能主线相关而性能主线又和数据结构、异步机制、RDB、AOF重写相关。找到了影响的因素解决起来也就很容易了。
另外,在学习和使用的过程中,你完全可以根据你自己的方式,完善这张画像图,把你自己实践或掌握到的新知识点,按照“问题 --> 主线 --> 技术点”的方式梳理出来,放到这张图上。这样一来,你的积累越来越多,画像也会越来越丰富。以后在遇到问题的时候,就很容易解决了。
## 课程是如何设计的?
刚刚说的这些,其实也正是咱们这个课程的核心设计理念。接下来,我就说说这门课具体是怎么设计的。
**基础篇:打破技术点之间的壁垒,带你建立网状知识结构**
我会先从构造一个简单的键值数据库入手,带你庖丁解牛。这有点像是建房子,只有顶梁柱确定了,房子有形了,你才能去想“怎么设计更美、更实用”的问题。因此,在“基础篇”,我会具体讲解数据结构、线程模型、持久化等几根“顶梁柱”,让你不仅能抓住重点,还能明白它们在整体框架中的地位和作用,以及它们之间的相互联系。明白了这些,也就打好了基础。
**实践篇:场景和案例驱动,取人之长,梳理出一套属于你自己的“武林秘籍”**
前面说过,从应用的维度来说,在学习时,我们需要以“场景”和“案例”作为驱动。因此,在“实践篇”,我也会从这两大层面来进行讲解。
在“案例”层面,我会介绍数据结构的合理使用、避免请求阻塞和抖动、避免内存竞争和提升内存使用效率的关键技巧;在“场景”层面,我会重点介绍缓存和集群两大场景。
对于缓存而言,我会重点讲解缓存基本原理及淘汰策略,还有雪崩、穿透、污染等异常情况;对于集群来说,我会围绕集群方案优化、数据一致性、高并发访问等问题,和你聊聊可行的解决方案。
**未来篇:具有前瞻性,解锁新特性**
Redis 6.0刚刚推出增加了万众瞩目的多线程等新特性因此我会向你介绍这些新特性以及当前业界对Redis的最新探索这会让你拥有前瞻性视角了解Redis的发展路线图为未来的发展提前做好准备。凡事预则立这样一来你就可以走在很多人的前面。
除此之外,我还会不定期进行加餐,跟你分享一些好的运维工具、定制化客户端开发的方法、经典的学习资料,等等,还会策划一些答疑,及时解决你的疑惑。
![](https://static001.geekbang.org/resource/image/13/7e/13946f7543f9eea58c9bd2b877826b7e.jpg?wh=750*4458)
最后我想说Redis是一个非常优秀的系统它在CPU使用、内存组织、存储持久化和网络通信这四大方面的设计非常经典而这些基本涵盖了一个优秀的后端系统工程师需要掌握的核心知识和关键技术。希望你通过这个课程的学习成长为一名优秀的系统工程师。
不过一个人单枪匹马地去学习往往很难坚持下去。如果你身边也有在使用Redis的同学我希望你能帮忙把这个课程分享给他/她,你们可以一起学习,互相鼓励。欢迎多多给我留言,你们的鼓励是我持续产出好内容的动力。