Redis 概览

Redis 知识全景图

Redis 问题画像图

基础篇

基本架构

数据结构

数据类型和底层数据结构映射关系

全局哈希表


链式哈希解决哈希冲突

渐进式 rehash

不同数据结构查找操作的时间复杂度

不同操作的复杂度

  • 单元素操作是基础;
  • 范围操作非常耗时;
  • 统计操作通常高效;
  • 例外情况只有几个。

第一,单元素操作,是指每一种集合类型对单个数据实现的增删改查操作。例如,Hash 类型的 HGET、HSET 和 HDEL,Set 类型的 SADD、SREM、SRANDMEMBER 等。这些操作的复杂度由集合采用的数据结构决定,例如,HGET、HSET 和 HDEL 是对哈希表做操作,所以它们的复杂度都是 O(1);Set 类型用哈希表作为底层数据结构时,它的 SADD、SREM、SRANDMEMBER 复杂度也是 O(1)。这里,有个地方你需要注意一下,集合类型支持同时对多个元素进行增删改查,例如 Hash 类型的 HMGET 和 HMSET,Set 类型的 SADD 也支持同时增加多个元素。此时,这些操作的复杂度,就是由单个元素操作复杂度和元素个数决定的。例如,HMSET 增加 M 个元素时,复杂度就从 O(1) 变成 O(M) 了。

第二,范围操作,是指集合类型中的遍历操作,可以返回集合中的所有数据,比如 Hash 类型的 HGETALL 和 Set 类型的 SMEMBERS,或者返回一个范围内的部分数据,比如 List 类型的 LRANGE 和 ZSet 类型的 ZRANGE。这类操作的复杂度一般是 O(N),比较耗时,我们应该尽量避免

不过,Redis 从 2.8 版本开始提供了 SCAN 系列操作(包括 HSCAN,SSCAN 和 ZSCAN),这类操作实现了渐进式遍历,每次只返回有限数量的数据。这样一来,相比于 HGETALL、SMEMBERS 这类操作来说,就避免了一次性返回所有元素而导致的 Redis 阻塞。

第三,统计操作,是指集合类型对集合中所有元素个数的记录,例如 LLEN 和 SCARD。这类操作复杂度只有 O(1),这是因为当集合类型采用压缩列表、双向链表、整数数组这些数据结构时,这些结构中专门记录了元素的个数统计,因此可以高效地完成相关操作。

第四,例外情况,是指某些数据结构的特殊记录,例如压缩列表和双向链表都会记录表头和表尾的偏移量。这样一来,对于 List 类型的 LPOP、RPOP、LPUSH、RPUSH 这四个操作来说,它们是在列表的头尾增删元素,这就可以通过偏移量直接定位,所以它们的复杂度也只有 O(1),可以实现快速操作。

高性能IO模型

通常说,Redis 是单线程,主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的,这也是 Redis 对外提供键值存储服务的主要流程。但 Redis 的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。

Redis 为什么用单线程?

多线程存在开销

  1. 多线程编程模式面临共享资源的并发访问控制问题。
  2. 线程上下文切换的开销

单线程 Redis 为什么那么快?

多路复用机制

基本 IO 模型与阻塞点


在这里的网络 IO 操作中,有潜在的阻塞点,分别是 accept() 和 recv()。当 Redis 监听到一个客户端有连接请求,但一直未能成功建立起连接时,会阻塞在 accept() 函数这里,导致其他客户端无法和 Redis 建立连接。类似的,当 Redis 通过 recv() 从一个客户端读取数据时,如果数据一直没有到达,Redis 也会一直阻塞在 recv()。

这就导致 Redis 整个线程阻塞,无法处理其他客户端请求,效率很低。不过,幸运的是,socket 网络模型本身支持非阻塞模式。

非阻塞模式

在 socket 模型中,不同操作调用后会返回不同的套接字类型。socket() 方法会返回主动套接字,然后调用 listen() 方法,将主动套接字转化为监听套接字,此时,可以监听来自客户端的连接请求。最后,调用 accept() 方法接收到达的客户端连接,并返回已连接套接字。

针对监听套接字,我们可以设置非阻塞模式:当 Redis 调用 accept() 但一直未有连接请求到达时,Redis 线程可以返回处理其他操作,而不用一直等待。但是,你要注意的是,调用 accept() 时,已经存在监听套接字了。

虽然 Redis 线程可以不用继续等待,但是总得有机制继续在监听套接字上等待后续连接请求,并在有请求时通知 Redis。

类似的,我们也可以针对已连接套接字设置非阻塞模式:Redis 调用 recv() 后,如果已连接套接字上一直没有数据到达,Redis 线程同样可以返回处理其他操作。我们也需要有机制继续监听该已连接套接字,并在有数据达到时通知 Redis。

这样才能保证 Redis 线程,既不会像基本 IO 模型中一直在阻塞点等待,也不会导致 Redis 无法处理实际到达的连接请求或数据。

到此,Linux 中的 IO 多路复用机制就要登场了。

基于多路复用的高性能 I/O 模型

Linux 中的 IO 多路复用机制是指一个线程处理多个 IO 流,就是我们经常听到的 select/epoll 机制。简单来说,在 Redis 只运行单线程的情况下,该机制允许内核中,同时存在多个监听套接字和已连接套接字

下图就是基于多路复用的 Redis IO 模型。图中的多个 FD 就是刚才所说的多个套接字。Redis 网络框架调用 epoll 机制,让内核监听这些套接字。此时,Redis 线程不会阻塞在某一个特定的监听或已连接套接字上,也就是说,不会阻塞在某一个特定的客户端请求处理上。正因为此,Redis 可以同时和多个客户端连接并处理请求,从而提升并发性。

为了在请求到达时能通知到 Redis 线程,select/epoll 提供了基于事件的回调机制即针对不同事件的发生,调用相应的处理函数

那么,回调机制是怎么工作的呢?其实,select/epoll 一旦监测到 FD 上有请求到达时,就会触发相应的事件。

这些事件会被放进一个事件队列,Redis 单线程对该事件队列不断进行处理。这样一来,Redis 无需一直轮询是否有请求实际发生,这就可以避免造成 CPU 资源浪费。同时,Redis 在对事件队列中的事件进行处理时,会调用相应的处理函数,这就实现了基于事件的回调。因为 Redis 一直在对事件队列进行处理,所以能及时响应客户端请求,提升 Redis 的响应性能。

持久化

参考:极客时间 Redis核心技术与实战 笔记(基础篇 AOF和RDB)

主从同步、哨兵机制、切片集群

参考:极客时间 Redis核心技术与实战 笔记(基础篇 集群)

极客时间 Redis核心技术与实战 笔记(基础篇)相关推荐

  1. 极客时间 Redis核心技术与实战 笔记(实践篇 集群)

    Redis主从同步与故障切换,有哪些坑? 主从数据不一致 原因:主从库间的命令复制是异步进行的 从库会滞后执行同步命令的原因: 主从库间的网络可能会有传输延迟,所以从库不能及时地收到主库发送的命令,从 ...

  2. 《极客时间·每日一课》笔记

    秒杀服务的限流策略 合法性限流 鉴定非法请求: 验证码(剔除机器人,使用户的请求时间随机分布) 非法IP限制 隐藏秒杀按钮入口 负载限流 负载均衡分发请求到每个服务器 多级(级联)负载,第二层MAC负 ...

  3. Elastic 极客时间 阮一鸣 学习笔记_入门

    资料链接:https://github.com/MINCWANG/geektime-ELK 版本迭代 插件在线安装(中文ik分词器) 启停 Kibana 快捷键 documnet index ES m ...

  4. 用户体验地图的一个不错的例子(极客时间用户体验设计课笔记)

    1 要根据用户不同的角色去划分用户体验地图 用户体验地图要和用户角色相对应 ,不仅要明确体验地图对应的目标用户,更要 明确目标用户下不同的用户角色,一个角色对应一份体验地图. 2  一个完整的例子:

  5. Linux CentOS 系统实战笔记-基础篇

    CentOS 日常笔记 1.Linux基础命令1 2.Linux基础命令2 3.输入输出重定向 4.Linux下目录分类与作用 5.虚拟机与物理机时间同步 6. VIM 神之编辑器 7. Linux ...

  6. 【极客时间】《Java并发编程实战》学习笔记

    目录: 开篇词 | 你为什么需要学习并发编程? 内容来源:开篇词 | 你为什么需要学习并发编程?-极客时间 例如,Java 里 synchronized.wait()/notify() 相关的知识很琐 ...

  7. 极客时间课程《Python核心技术与实战》课程练习实践

    GitHub - zwdnet/PythonPractice: 极客时间课程<Python核心技术与实战>课程练习实践.极客时间课程<Python核心技术与实战>课程练习实践. ...

  8. 本人亲自整理的极客时间设计模式之美的硬核笔记

    由于笔记内容过多,我把它放到语雀上了. 点击我 以下内容是为了让搜索引擎,检测到这篇文章.要阅读体验,请点击上面的连接"点击我",去我的语雀看.对了,我看到语雀那里有投诉的功能,请 ...

  9. Redis核心技术与实战-蒋德钧-课程笔记

    一.Redis知识全景图 二.Redis问题画像图 参考资料: 极客时间<Redis核心技术与实战>课程

最新文章

  1. Python中matplotlib默认绘制的条形图比较胖?如何设置成体型匀称的条形图,达到最佳的可视化效果。
  2. 深入解析Android关机
  3. oracle里面有emp表么,Oracle自带表(EMP)SQL语句练习
  4. Multi Dimension 数据库设计
  5. memcpy后数据不对_详解Redis 的 5 种基本数据结构:
  6. [转载][总结]函数getopt(),getopt_long及其参数optind
  7. java文件解压文件_java 文件解压缩
  8. 习题6-2 使用函数求特殊a串数列和 (20 分)
  9. C#LeetCode刷题之#884-两句话中的不常见单词(Uncommon Words from Two Sentences)
  10. matlab帮助_【MATLAB】使用 APP DESIGNER 模块来帮助你做参数设计
  11. 募资补充粮草、成交额翻倍增长,想翻身的国美开始造势
  12. oc 经常用到弹出view的方法
  13. 活化脂修饰NOTA,NOTA-NHS ester,CAS:1338231-09-6
  14. 现代软件工程 第一章 【概论】练习与讨论 第10题 邓杰
  15. c语言最大乘积问题,利用C语言来求最大连续子序列乘积的方法
  16. Numpy:随机抽样
  17. “阿里/字节“大厂自动化测试面试题一般会问什么?以及技巧和答案
  18. 服务器查看系统盘位置,服务器上查看硬盘位置
  19. 计算机桌面都有说明,电脑桌面上所有图标都消失了的四种处理方法
  20. android 车载蓝牙模块,安卓APP通过蓝牙串口模块控制DSP车机收音机

热门文章

  1. 关于Android app正式版本和测试版本的切换
  2. CentOS下的服务器审计系统:script
  3. 「微信群合影2.3.0」- 新增高清头像
  4. 把照片唱给你听 | 腾讯AI Lab国际领先技术邀你「趣」体验
  5. mysql中如何分页查询_MySQL_mysql分页原理和高效率的mysql分页查询语句,以前我在mysql中分页都是用的 l - phpStudy...
  6. 微信中域名网站域名被封锁、被屏蔽、被和谐后的解决方法
  7. 连就连,你我相约定百年。谁若97岁死,奈何桥上等三年!
  8. java腾讯地图根据经纬度获取具体位置
  9. 如何设计一个混沌工程实验?
  10. 1-13 格式化输出