Redis深度历险
Redis 深度历险:核心原理与应用实践
一直不懂
笔记
展开
-
【Redis核心原理和应用实践】源码 7:极度深寒 —— 探索「基数树」内部
Rax 是 Redis 内部比较特殊的一个数据结构,它是一个有序字典树 (基数树 RadixTree),按照 key 的字典序排列,支持快速地定位、插入和删除操作。Redis 五大基础数据结构里面,能作为字典使用的有 hash 和 zset。hash 不具备排序功能,zset 则是按照 score 进行排序的。rax 跟 zset 的不同在于它是按照 key 进行排序的。Redis 作者认为 r...转载 2019-12-29 01:22:01 · 177 阅读 · 0 评论 -
【Redis核心原理和应用实践】源码 6:极度深寒 —— 探索「 紧凑列表」内部
Redis 5.0 又引入了一个新的数据结构 listpack,它是对 ziplist 结构的改进,在存储空间上会更加节省,而且结构上也比 ziplist 要精简。它的整体形式和 ziplist 还是比较接近的,如果你认真阅读了 ziplist 的内部结构分析,那么 listpack 也是比较容易理解的。struct listpack<T> { int32 total_...转载 2019-12-29 01:21:51 · 237 阅读 · 0 评论 -
【Redis核心原理和应用实践】源码 5:极度深寒 —— 探索「跳跃列表」内部结构
Redis 的 zset 是一个复合结构,一方面它需要一个 hash 结构来存储 value 和 score 的对应关系,另一方面需要提供按照 score 来排序的功能,还需要能够指定 score 的范围来获取 value 列表的功能,这就需要另外一个结构「跳跃列表」。zset 的内部实现是一个 hash 字典加一个跳跃列表 (skiplist)。hash 结构在讲字典结构时已经详细分析过...转载 2019-12-29 01:21:40 · 186 阅读 · 0 评论 -
【Redis核心原理和应用实践】源码 4:极度深寒 —— 探索「 快速列表」内部
Redis 早期版本存储 list 列表数据结构使用的是压缩列表 ziplist 和普通的双向链表linkedlist,也就是元素少时用 ziplist,元素多时用 linkedlist。// 链表的节点struct listNode<T> { listNode* prev; listNode* next; T value;}// 链...转载 2019-12-29 01:21:26 · 145 阅读 · 0 评论 -
【Redis核心原理和应用实践】源码 3:极度深寒 —— 探索 「压缩列表」内部
Redis 为了节约内存空间使用,zset 和 hash 容器对象在元素个数较少的时候,采用压缩列表 (ziplist) 进行存储。压缩列表是一块连续的内存空间,元素之间紧挨着存储,没有任何冗余空隙。> zadd programmings 1.0 go 2.0 python 3.0 java(integer) 3> debug object programmings...转载 2019-12-29 01:21:19 · 181 阅读 · 0 评论 -
【Redis核心原理和应用实践】源码 2:极度深寒 —— 探索「字典」内部
dict 是 Redis 服务器中出现最为频繁的复合型数据结构,除了 hash 结构的数据会用到字典外,整个 Redis 数据库的所有 key 和 value 也组成了一个全局字典,还有带过期时间的 key 集合也是一个字典。zset 集合中存储 value 和 score 值的映射关系也是通过 dict 结构实现的。struct RedisDb { dict* dict; //...转载 2019-12-29 01:21:11 · 184 阅读 · 0 评论 -
【Redis核心原理和应用实践】源码 1:极度深寒 —— 探索「字符串」内部结构
Redis 中的字符串是可以修改的字符串,在内存中它是以字节数组的形式存在的。我们知道 C 语言里面的字符串标准形式是以 NULL 作为结束符,但是在 Redis 里面字符串不是这么表示的。因为要获取 NULL 结尾的字符串的长度使用的是 strlen 标准库函数,这个函数的算法复杂度是 O(n),它需要对字节数组进行遍历扫描,作为单线程的 Redis 表示承受不起。Redis 的字符串叫着「...转载 2019-12-29 01:21:00 · 173 阅读 · 0 评论 -
【Redis核心原理和应用实践】拓展 9:隔墙有耳 —— Redis 安全通信
想象这样一个应用场景,公司有两个机房。因为一个紧急需求,需要跨机房读取 Redis数据。应用部署在 A 机房,存储部署在 B 机房。如果使用普通 tcp 直接访问,因为跨机房所以传输数据会暴露在公网,这非常不安全,客户端服务器交互的数据存在被窃听的风险。Redis 本身并不支持 SSL 安全链接,不过有了 SSL 代理软件,我们可以让通信数据透明地得到加密,就好像 Redis 穿上了一层...转载 2019-12-29 01:20:27 · 285 阅读 · 0 评论 -
【Redis核心原理和应用实践】拓展 8:居安思危 —— 保护 Redis
本节我们来谈谈使用 Redis 需要注意的安全风险以及防范措施,避免数据泄露和丢失,避免所在主机权限被黑客窃取,以及避免人为操作失误。指令安全Redis 有一些非常危险的指令,这些指令会对 Redis 的稳定以及数据安全造成非常严重的影响。比如 keys 指令会导致 Redis 卡顿,flushdb 和 flushall 会让 Redis 的所有数据全部清空。如何避免人为操作失误导致这...转载 2019-12-29 01:20:11 · 362 阅读 · 0 评论 -
【Redis核心原理和应用实践】拓展 7:妙手仁心 —— 优雅地使用 Jedis
本节面向 Java 用户,主题是如何优雅地使用 Jedis 编写应用程序,既可以让代码看起来赏心悦目,又可以避免使用者犯错。Jedis 是 Java 用户最常用的 Redis 开源客户端。它非常小巧,实现原理也很简单,最重要的是很稳定,而且使用的方法参数名称和官方的文档非常 match,如果有什么方法不会用,直接参考官方的指令文档阅读一下就会了,省去了非必要的重复学习成本。不像有些客户端把方法...转载 2019-12-29 01:19:56 · 134 阅读 · 0 评论 -
【Redis核心原理和应用实践】拓展 6:平波缓进 —— 懒惰删除
一直以来我们认为 Redis 是单线程的,单线程为 Redis 带来了代码的简洁性和丰富多样的数据结构。不过 Redis 内部实际上并不是只有一个主线程,它还有几个异步线程专门用来处理一些耗时的操作。Redis 为什么要懒惰删除(lazy free)?删除指令 del 会直接释放对象的内存,大部分情况下,这个指令非常快,没有明显延迟。不过如果删除的 key 是一个非常大的对象,比如一个包...转载 2019-12-29 01:19:52 · 169 阅读 · 0 评论 -
【Redis核心原理和应用实践】拓展 5:优胜劣汰 —— LRU
当 Redis 内存超出物理内存限制时,内存的数据会开始和磁盘产生频繁的交换 (swap)。交换会让 Redis 的性能急剧下降,对于访问量比较频繁的 Redis 来说,这样龟速的存取效率基本上等于不可用。在生产环境中我们是不允许 Redis 出现交换行为的,为了限制最大使用内存,Redis 提供了配置参数 maxmemory 来限制内存超出期望大小。当实际内存超出 maxmemory ...转载 2019-12-29 01:19:41 · 196 阅读 · 0 评论 -
【Redis核心原理和应用实践】拓展 4:朝生暮死 —— 过期策略
Redis 所有的数据结构都可以设置过期时间,时间一到,就会自动删除。你可以想象Redis 内部有一个死神,时刻盯着所有设置了过期时间的 key,寿命一到就会立即收割。你还可以进一步站在死神的角度思考,会不会因为同一时间太多的 key 过期,以至于忙不过来。同时因为 Redis 是单线程的,收割的时间也会占用线程的处理时间,如果收割的太过于繁忙,会不会导致线上读写指令出现卡顿。这些问题...转载 2019-12-29 01:19:32 · 204 阅读 · 0 评论 -
【Redis核心原理和应用实践】拓展 3:拾遗漏补 —— 再谈分布式锁
在第三节,我们细致讲解了分布式锁的原理,它的使用非常简单,一条指令就可以完成加锁操作。不过在集群环境下,这种方式是有缺陷的,它不是绝对安全的。比如在 Sentinel 集群中,主节点挂掉时,从节点会取而代之,客户端上却并没有明显感知。原先第一个客户端在主节点中申请成功了一把锁,但是这把锁还没有来得及同步到从节点,主节点突然挂掉了。然后从节点变成了主节点,这个新的节点内部没有这个锁,所以当另一个...转载 2019-12-29 01:19:23 · 196 阅读 · 0 评论 -
【Redis核心原理和应用实践】拓展 2:无所不知 —— Info 指令
在使用 Redis 时,时常会遇到很多问题需要诊断,在诊断之前需要了解 Redis 的运行状态,通过强大的 Info 指令,你可以清晰地知道 Redis 内部一系列运行参数。Info 指令显示的信息非常繁多,分为 9 大块,每个块都有非常多的参数,这 9 个块分别是: 1、Server 服务器运行的环境参数 2、Clients 客户端相关信息 3、Memory 服...转载 2019-12-29 01:19:15 · 167 阅读 · 0 评论 -
【Redis核心原理和应用实践】拓展 1:耳听八方 —— Stream
Redis5.0 被作者 Antirez 突然放了出来,增加了很多新的特色功能。而 Redis5.0 最大的新特性就是多出了一个数据结构 Stream,它是一个新的强大的支持多播的可持久化的消息队列,作者坦言 Redis Stream 狠狠地借鉴了 Kafka 的设计。Redis Stream 的结构如上图所示,它有一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的 ID 和...转载 2019-12-29 01:19:07 · 395 阅读 · 0 评论 -
【Redis核心原理和应用实践】集群 3:众志成城 —— Cluster
RedisCluster 是 Redis 的亲儿子,它是 Redis 作者自己提供的 Redis 集群化方案。相对于 Codis 的不同,它是去中心化的,如图所示,该集群有三个 Redis 节点组成,每个节点负责整个集群的一部分数据,每个节点负责的数据多少可能不一样。这三个节点相互连接组成一个对等的集群,它们之间通过一种特殊的二进制协议相互交互集群信息。Redis Cluster 将所...转载 2019-12-29 01:18:39 · 363 阅读 · 0 评论 -
【Redis核心原理和应用实践】集群 2:分而治之 —— Codis
在大数据高并发场景下,单个 Redis 实例往往会显得捉襟见肘。首先体现在内存上,单个 Redis 的内存不宜过大,内存太大会导致 rdb 文件过大,进一步导致主从同步时全量同步时间过长,在实例重启恢复时也会消耗很长的数据加载时间,特别是在云环境下,单个实例内存往往都是受限的。其次体现在 CPU 的利用率上,单个 Redis 实例只能利用单个核心,这单个核心要完成海量数据的存取和管理工作压力会非常...转载 2019-12-29 01:18:28 · 211 阅读 · 0 评论 -
【Redis核心原理和应用实践】集群 1:李代桃僵 —— Sentinel
目前我们讲的 Redis 还只是主从方案,最终一致性。读者们可思考过,如果主节点凌晨3 点突发宕机怎么办?就坐等运维从床上爬起来,然后手工进行从主切换,再通知所有的程序把地址统统改一遍重新上线么?毫无疑问,这样的人工运维效率太低,事故发生时估计得至少 1 个小时才能缓过来。如果是一个大型公司,这样的事故足以上新闻了。所以我们必须有一个高可用方案来抵抗节点故障,当故障发生时可以自动进行从主切换...转载 2019-12-29 01:18:18 · 161 阅读 · 0 评论 -
【Redis核心原理和应用实践】原理 8:有备无患 —— 主从同步
很多企业都没有使用到 Redis 的集群,但是至少都做了主从。有了主从,当 master 挂掉的时候,运维让从库过来接管,服务就可以继续,否则 master 需要经过数据恢复和重启的过程,这就可能会拖很长的时间,影响线上业务的持续服务。在了解 Redis 的主从复制之前,让我们先来理解一下现代分布式系统的理论基石——CAP 原理。CAP 原理CAP 原理就好比分布式领域的牛顿定律,它...转载 2019-12-29 01:17:24 · 177 阅读 · 0 评论 -
【Redis核心原理和应用实践】原理 7:开源节流 —— 小对象压缩
Redis 是一个非常耗费内存的数据库,它所有的数据都放在内存里。如果我们不注意节约使用内存,Redis 就会因为我们的无节制使用出现内存不足而崩溃。Redis 作者为了优化数据结构的内存占用,也苦心孤诣增加了非常多的优化点,这些优化也是以牺牲代码的可读性为代价的,但是毫无疑问这是非常值得的,尤其像 Redis 这种数据库。32bit vs 64bitRedis 如果使用 32bit ...转载 2019-12-29 01:17:12 · 186 阅读 · 0 评论 -
【Redis核心原理和应用实践】原理 6:小道消息 —— PubSub
前面我们讲了 Redis 消息队列的使用方法,但是没有提到 Redis 消息队列的不足之消息队列的不足之处,那就是它不支持消息的多播机制处,那就是它不支持消息的多播机制。消息多播消息多播允许生产者生产一次消息,中间件负责将消息复制到多个消息队列,每个消息队列由相应的消费组进行消费。它是分布式系统常用的一种解耦方式,用于将多个消费组的逻辑进行拆分。支持了消息多播,多个消费组的逻辑就可以放...转载 2019-12-29 01:16:57 · 183 阅读 · 0 评论 -
【Redis核心原理和应用实践】原理 5:同舟共济 —— 事务
为了确保连续多个操作的原子性,一个成熟的数据库通常都会有事务支持,Redis 也不例外。Redis 的事务使用非常简单,不同于关系数据库,我们无须理解那么多复杂的事务模型,就可以直接使用。不过也正是因为这种简单性,它的事务模型很不严格,这要求我们不能像使用关系数据库的事务一样来使用 Redis。Redis 事务的基本使用每个事务的操作都有 begin、commit 和 rollback...转载 2019-12-29 01:16:45 · 151 阅读 · 0 评论 -
【Redis核心原理和应用实践】原理 4:雷厉风行 —— 管道
大多数同学一直以来对 Redis 管道有一个误解,他们以为这是 Redis 服务器提供的一种特别的技术,有了这种技术就可以加速 Redis 的存取效率。但是实际上 Redis 管道(Pipeline) 本身并不是 Redis 服务器直接提供的技术,这个技术本质上是由客户端提供的,跟服务器没有什么直接的关系。下面我们对这块做一个深入探究。Redis 的消息交互当我们使用客户端对 Redi...转载 2019-12-29 01:16:34 · 180 阅读 · 0 评论 -
【Redis核心原理和应用实践】原理 3:未雨绸缪 —— 持久化
Redis 的数据全部在内存里,如果突然宕机,数据就会全部丢失,因此必须有一种机制来保证 Redis 的数据不会因为故障而丢失,这种机制就是 Redis 的持久化机制。Redis 的持久化机制有两种,第一种是快照,第二种是 AOF 日志。快照是一次全量备份,AOF 日志是连续的增量备份。快照是内存数据的二进制序列化形式,在存储上非常紧凑,而 AOF 日志记录的是内存数据修改的指令记录文本。AO...转载 2019-12-29 01:16:23 · 194 阅读 · 0 评论 -
【Redis核心原理和应用实践】原理 2:交头接耳 —— 通信协议
Redis 的作者认为数据库系统的瓶颈一般不在于网络流量,而是数据库自身内部逻辑处理上。所以即使 Redis 使用了浪费流量的文本协议,依然可以取得极高的访问性能。Redis将所有数据都放在内存,用一个单线程对外提供服务,单个节点在跑满一个 CPU 核心的情况下可以达到了 10w/s 的超高 QPS。RESP(Redis Serialization Protocol)RESP 是 R...转载 2019-12-29 01:16:09 · 151 阅读 · 0 评论 -
【Redis核心原理和应用实践】原理 1:鞭辟入里 —— 线程 IO 模型
Redis 是个单线程程序!这点必须铭记。也许你会怀疑高并发的 Redis 中间件怎么可能是单线程。很抱歉,它就是单线程,你的怀疑暴露了你基础知识的不足。莫要瞧不起单线程,除了 Redis 之外,Node.js 也是单线程,Nginx 也是单线程,但是它们都是服务器高性能的典范。Redis 单线程为什么还能这么快?因为它所有的数据都在内存中,所有的运算都是内存级别的运算。正因为 Red...转载 2019-12-29 01:16:00 · 287 阅读 · 0 评论 -
【Redis核心原理和应用实践】应用 9:大海捞针 —— Scan
在平时线上 Redis 维护工作中,有时候需要从 Redis 实例成千上万的 key 中找出特定前缀的 key 列表来手动处理数据,可能是修改它的值,也可能是删除 key。这里就有一个问题,如何从海量的 key 中找出满足特定前缀的 key 列表来?Redis 提供了一个简单暴力的指令 keys 用来列出所有满足特定正则字符串规则的 key。127.0.0.1:6379> set...转载 2019-12-29 01:14:57 · 178 阅读 · 0 评论 -
【Redis核心原理和应用实践】应用 8:近水楼台 —— GeoHash
Redis 在 3.2 版本以后增加了地理位置 GEO 模块,意味着我们可以使用 Redis 来实现摩拜单车「附近的 Mobike」、美团和饿了么「附近的餐馆」这样的功能了。用数据库来算附近的人地图元素的位置数据使用二维的经纬度表示,经度范围 (-180, 180],纬度范围 (-90,90],纬度正负以赤道为界,北正南负,经度正负以本初子午线 (英国格林尼治天文台) 为界,东正西负...转载 2019-12-29 01:14:23 · 195 阅读 · 0 评论 -
【Redis核心原理和应用实践】应用 7:一毛不拔 —— 漏斗限流
漏斗限流是最常用的限流方法之一,顾名思义,这个算法的灵感源于漏斗(funnel)的结构。漏斗的容量是有限的,如果将漏嘴堵住,然后一直往里面灌水,它就会变满,直至再也装不进去。如果将漏嘴放开,水就会往下流,流走一部分之后,就又可以继续往里面灌水。如果漏嘴流水的速率大于灌水的速率,那么漏斗永远都装不满。如果漏嘴流水速率小于灌水的速率,那么一旦漏斗满了,灌水就需要暂停并等待漏斗腾空。所以...转载 2019-12-29 01:13:40 · 241 阅读 · 0 评论 -
【Redis核心原理和应用实践】应用 6:断尾求生 —— 简单限流
限流算法在分布式领域是一个经常被提起的话题,当系统的处理能力有限时,如何阻止计划外的请求继续对系统施压,这是一个需要重视的问题。老钱在这里用 “断尾求生” 形容限流背后的思想,当然还有很多成语也表达了类似的意思,如弃卒保车、壮士断腕等等。除了控制流量,限流还有一个应用目的是用于控制用户行为,避免垃圾请求。比如在UGC 社区,用户的发帖、回复、点赞等行为都要严格受控,一般要严格限定某行为在规定...转载 2019-12-29 01:12:39 · 228 阅读 · 0 评论 -
【Redis核心原理和应用实践】应用 5:层峦叠嶂 —— 布隆过滤器
上一节我们学会了使用 HyperLogLog 数据结构来进行估数,它非常有价值,可以解决很多精确度不高的统计需求。但是如果我们想知道某一个值是不是已经在 HyperLogLog 结构里面了,它就无能为力了,它只提供了 pfadd 和 pfcount 方法,没有提供 pfcontains 这种方法。讲个使用场景,比如我们在使用新闻客户端看新闻时,它会给我们不停地推荐新的内容,它每次推荐时要去...转载 2019-12-29 01:11:54 · 173 阅读 · 0 评论 -
【Redis核心原理和应用实践】应用 4:四两拨千斤 —— HyperLogLog
在开始这一节之前,我们先思考一个常见的业务问题:如果你负责开发维护一个大型的网站,有一天老板找产品经理要网站每个网页每天的 UV 数据,然后让你来开发这个统计模块,你会如何实现?如果统计 PV 那非常好办,给每个网页一个独立的 Redis 计数器就可以了,这个计数器的 key 后缀加上当天的日期。这样来一个请求,incrby 一次,最终就可以统计出所有的 PV数据。但是 UV 不一样,它...转载 2019-12-29 01:10:25 · 223 阅读 · 0 评论 -
【Redis核心原理和应用实践】应用 3:节衣缩食 —— 位图
在我们平时开发过程中,会有一些 bool 型数据需要存取,比如用户一年的签到记录,签了是 1,没签是 0,要记录 365 天。如果使用普通的 key/value,每个用户要记录 365个,当用户上亿的时候,需要的存储空间是惊人的。为了解决这个问题,Redis 提供了位图数据结构,这样每天的签到记录只占据一个位,365 天就是 365 个位,46 个字节 (一个稍长一点的字符串) 就可以完全容...转载 2019-12-29 01:08:54 · 148 阅读 · 0 评论 -
【Redis核心原理和应用实践】应用 2:缓兵之计 —— 延时队列
我们平时习惯于使用 Rabbitmq 和 Kafka 作为消息队列中间件,来给应用程序之间增加异步消息传递功能。这两个中间件都是专业的消息队列中间件,特性之多超出了大多数人的理解能力。使用过 Rabbitmq 的同学知道它使用起来有多复杂,发消息之前要创建 Exchange,再创建 Queue, 还要将 Queue 和 Exchange 通过某种规则绑定起来, 发消息的时候要指定 routin...转载 2019-12-29 01:06:51 · 206 阅读 · 0 评论 -
【Redis核心原理和应用实践】应用 1:千帆竞发 —— 分布式锁
分布式应用进行逻辑处理时经常会遇到并发问题。比如一个操作要修改用户的状态,修改状态需要先读出用户的状态,在内存里进行修改,改完了再存回去。如果这样的操作同时进行了,就会出现并发问题,因为读取和保存状态这两个操作不是原子的。(Wiki 解释:所谓原子操作原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch 线程切换。)...转载 2019-12-29 01:04:04 · 191 阅读 · 0 评论 -
【Redis核心原理和应用实践】基础:万丈高楼平地起 —— Redis 基础数据结构
要体验 Redis,我们先从 Redis 安装说起。体验 Redis 需要使用 Linux 或者 Mac 环境,如果是 Windows 可以考虑使用虚拟机。主要方式有四种: 使用 Docker 安装。 通过 Github 源码编译。 直接安装 apt-get install(Ubuntu)、yum install(RedHat) 或者 brew install(Mac)。...转载 2019-12-29 01:03:00 · 227 阅读 · 0 评论 -
【Redis核心原理和应用实践】Redis 可以用来做什么可以用来做什么
Redis 的业务应用范围非常广泛,让我们以掘金技术社区(juejin.im)的帖子模块为实例,梳理一下,Redis 可以用在哪些地方?记录帖子的点赞数、评论数和点击数 (hash)。 记录用户的帖子 ID 列表 (排序),便于快速显示用户的帖子列表 (zset)。 记录帖子的标题、摘要、作者和封面信息,用于列表页展示 (hash)。 记录帖子的点赞用户 ID 列表,评论 I...转载 2019-12-29 01:01:01 · 133 阅读 · 0 评论