这是 Redis 开发运维实战的第一篇文章.
我先做个自我介绍. 我在快手工作, 负责公司亿万级别 Cache 相关工作. 在这之前, 我在阿里云 Redis 团队主要参与云上 Redis 的保障性工作, 以及 Redis 诊断系统的开发, 在那里我与各种使用 Redis 的公司打交道, 了解了他们各自不同的 Redis 使用场景, 遇到并解决了各种千奇百怪的问题. 更早之前, 我在搜狐视频开发了公司的 Redis 私有云平台 CacheCloud, 现在已经在 GitHub 开源, 已经在很多公司使用. 另外, 在工作之余我和我之前的 leader 张益军写过一本书《Redis 开发与运维》, 这本书在社区也受到很好的评价.
对于我来说, 从开始接触 Redis 到今天, 已经有 6 年时间了. 虽然 Redis 使用起来很简单, 但我相信, 不论你是在项目中使用 Redis, 还是在面试时被问到 Redis 相关的问题, 都还是会有这样或那样的疑问. 比如说怎么用 Redis 实现分布式锁, Redis 怎么处理过期键, 缓存雪崩, 穿透, 热点问题怎么处理, 持久化, 集群方案怎么选择, 如何优雅地给 Redis 做键值分析等等问题. 这些问题在 6 年前的时候, 我就觉得高深莫测, 不知道怎么入手解决.
任何事情都需要一个循序渐进的过程, 所以我骨子里根本不相信所谓的 "速成". 从一开始的 Redis 小白到现在同事眼中的半个 Redis 专家, 我前前后后摸索了很多年, 虽然比别人笨点, 但是都还一直慢慢前进. 细说起来, 我的经历可能与很多基础架构或者 DBA 的同学不同, 在工作开始的前几年里, 我是做业务开发的, 换句话说, 我就是一名 Java 程序员.
那我后来又怎么与 Redis 结缘的呢? 一切都要从下面的一次 "事故" 说起.
我在搜狐的时候, 主要负责视频推荐系统的开发, 由于涉及按照用户维度和视频维度操作推荐结果, Leader 选择 Redis 作为缓存, 底层使用 HBase 作为存储架构. 当时, 我们团队基本都在使用 Memcached, 我个人也对 Memcached 比较熟悉, 但之所以选择 Redis, 我想是因为它支持的数据结构比较丰富, 同时还支持持久化; 另外最重要的是 Redis 已经开始支持原生集群, 而 Memcached 主要使用客户端分片来实现集群功能, 实际上不是真正的分布式.
对当时的我来说, Redis 就是一个黑盒, 我只知道它提供了 5 种数据结构以及一些常用的命令, 其他更深入的就不甚了解了. 后来我接到一个这样的需求: 用户在浏览网站时, 需要实现保存和展示用户喜欢视频的功能. 于是, 我使用了 Redis 的有序集合数据结构:
一切都如此简单. 但是, 突然有一天晚上, 我们的推荐服务发出令人揪心的可用性报警, 网站部分区域出现了天窗 (全空白, 恰好没做降级), 一切都乱套了. 不过, 唯一幸运的是负责运维的同事可以判断在出现这个问题之前, 刚好上线了我做的这个功能, 于是经过简单的项目回滚之后暂时解决了这个问题.
出了问题肯定要复盘, 经过分析我们发现是接口遭到恶意刷新. 这就引出了另外两个问题: 一个是本身接口安全性的问题和故障降级问题, 这里先不展开讨论了; 另一个就是有序集合本身也没有做容量限制, Redis 内存暴增, Java 里出现了大量大对象, 造成频繁的 GC, 导致可用性下降.
后来, 随着推荐系统规模的扩大, 我们用到的 Redis 集群越来越多, 同时碰到的问题也越来越多, 随之系统稳定性的挑战也越来越大. 经过商议, 我们决定开发一个 Redis 的 PaaS 平台, 也就是前面说的 CacheCloud. 我们的初衷是做出一个通用的 Redis 平台, 一方面, 能标准化地运维手上的 Redis, 解放我们的运维压力; 另一方面, 希望它能够帮助业务快速定位问题, 同时通过这个过程让大家逐步熟悉 Redis 的相关知识.
经过几个月的努力, 项目成功上线. 一波宣传和推广后, 各个业务组都开始接入该平台, 由于我对 Redis 比较感兴趣, Leader 将这些工作全部交给我来负责. 但是始料未及的是, 各个业务组接入后, 由于使用场景以及业务的多态性, 几乎每天都有很多人找我处理各种问题, 譬如: 用你们的 Redis 为什么超时了? 为什么内存用得这么快? 集群的数据分布以及高可用怎么实现的? 客户端效率怎么上不去? 诸多问题, 把我搞得焦头烂额. 没办法, 既然自己负责了这块业务, 就必须解决这些问题. 于是我进一步阅读之前买来的书籍以及 Redis 官方文档, 甚至尝试直接从源码中找答案. 经过一段时间的努力, 我不仅把上面的问题基本解决了, 而且对于 Redis 的知识体系有了更进一步的认识. 我把每次遇到的问题都书写到个人博客中, 一两个月后不仅处理了大部分问题, 还积累了数十篇文章, 成长带来的成就感也爆棚.
到了阿里云和快手之后, 因为公司的体量越来越大, 我负责的 Redis 实例个数以及规模也越来越大, 问题同样也更是千奇百怪, 很多问题需要对 Redis 源码, 业务架构有更深入的理解和认识才能解决.
比如说在阿里云的时候, 有个客户反馈 Redis 内存突然暴增造成数据丢失, 希望我们给出具体原因, 我按照常规的内存分析方法均没有发现异常, 最后突然想到有可能是 Redis 的 rehash 造成的. 经过和同事看源码做试验, 最终找到原因, 果然是 Redis 的 rehash 所致
我经历的这几家公司所用的 Redis 分布式架构均不相同, 有官方的版本, 有自研的版本, 也有其他开源版本. 在使用和运维这些不同的架构中, 我理解了每种架构的优劣势和使用场景, 对于分布式存储架构也有了更深的认识,"独乐乐不如众乐乐", 我也希望能将这些理解传递给你, 启发到你, 进而帮助到你, 我们一起成长.
说了这么多, 其实是想表达一个核心的观点: 学习一门技术的最快方法就是带着问题来学. 千万不要相信网上有些观点说 "Redis 挺简单, 直接看源码就好了". 我想, 除非你是技术大牛, 否则这是不可能实现的, 对于普通人来讲 90% 的可能就是打退堂鼓. 所以, 我也希望这个公众号是带着这个思路来撰写的, 实际上 Redis 的核心点大概就如下几个: 数据结构的理解, 客户端的优化, 复制和持久化的选择, 分布式高可用的实现, 缓存设计与优化, 等等. 而我的公众号也围绕着这几点.
如何正确选择数据结构
基础编码不能忽视 - sds
Redis 到底能存储多少个键值对 - hashtable 解析
节省内存利器 - ziplist(压缩列表)
大列表怎么存 - quicklist(快速列表)
链表的二分查找 - skiplist(跳跃表)
你真的了解 Redis 里都是什么 key 吗?
事件模型分析: Redis 为什么这么快?
缓存的设计与优化 (一): 更新策略, 粒度, 穿透问题
缓存的设计与优化 (二): 无底洞问题
缓存的设计与优化 (三): 热点 key 问题
Redis 的典型使用场景: 分布式锁
Redis 的典型使用场景: 消息队列
Redis 的典型使用场景: 红包秒杀
BIO 还是 NIO 客户端
揪出 Redis 的性能瓶颈 (一): 客户端管理
持久化 RDB 和 AOF 的进化史
揪出 Redis 的性能瓶颈 (二): 持久化抉择
复制计划史: 全量复制, 部分复制, psync2
揪出 Redis 的性能瓶颈 (三): 复制的隐忧
Redis 内存开销在哪儿?
开源节流 (一): 干掉内存毒瘤死键问题
开源节流 (二): 键值对象优化
开源节流 (三): 内存碎片的解决之道
开源节流 (四): 小细节大用处
开源节流 (五): 硬件成本拯救者 Pika
高可用探针: Redis Sentinel
分布式缓存数据分布与实现方式
根红苗正集群方案: Redis Cluster 深入实践 (上)
根红苗正集群方案: Redis Cluster 深入实践 (下)
基于代理集群方案: Twemproxy
基于代理集群方案: Codis
基于 range 的集群方案: Redis range
Memcached 真的过时了吗?
除了 Redis 还有啥好用的?
小工具大用处: 我的 Redis 工具箱
是否该升级你的 Redis:"版本帝"Redis
Redis 同城容灾.
Redis 异地多活
Redis 安全七法: 你的 Redis 是否安全?
Linux 与 Redis:Linux 操作系统的配置优化
CacheCloud 的开发计划
《Redis 开发与运维》第二版计划等等
文章大体就这些内容, 我争取会一周更新一篇. 为什么要弄一个公众账号呢? 一方面是做个自我总结, 督促自己学习, 另一方面也是希望和大家讨论.
来源: http://www.tuicool.com/articles/6nYvA37