【Redis】全局命令/内部编码/浅谈单线程模型

embedded/2024/9/24 12:17:14/

目录

前言

两个核心命令

GET和SET

全局命令

KEYS

EXISTS 

DEL

EXPIRE

TTL

TYPE 

数据结构的内部编码

Redis的5中数据类型

Redis数据结构和内部编码

单线程架构


前言

Redis 提供了 5 种数据结构,理解每种数据结构的特点对于 Redis 开发运维⾮常重要,同时掌握每
种数据结构的常见命令,会在使用Redis 的时候做到游刃有余。在正式介绍 5 种数据结构之前,了解⼀下 Redis 的⼀些全局命令。单线程命令处理机制是⼗分必要的,它们能为后⾯内容的学习打下⼀个良好的基础。

注意:

  • Redis 的命令有上百个,如果纯靠死记硬背⽐较困难,但是如果理解 Redis 的⼀些机制,会发现这些命令有很强的通⽤性。
  • Redis 不是万⾦油,有些数据结构和命令必须在特定场景下使⽤,⼀旦使⽤不当可能对 Redis 本⾝或者应⽤本⾝造成致命伤害。

两个核心命令

GET和SET

这两个命令是Redis中最核心的两个命令,因为Redis是按照键值对的方式存储数据的;GET命令是根据KEY来取对应的value的,而SET是把一对key-value存储进去;

说明:

  • 使用SET存储一对KV值时,在命令行上敲的是字符串,但是对于value可能是不同的数据结构;
  • KV值可以加上单引号,双引号,也可以不加;

示例:

说明:

  • GET命令直接输入key就可以得到value;
  • 如果当前key不存在,回返回 nil;
  • Redis中的命令不区分大小写; 

全局命令

Redis支持很多种数据结构,包括:字符串、哈希表、列表、集合、有序集合等;对于key固定的就是字符串,但是value实际上会有很多种类型,操作不同的数据结构就会有不同的命令;因此我们在学习Redis中的数据结构之前,先了解一些全局命令:就是能够搭配任意一个数据结构来使用的命令;

KEYS

功能:用来查询当前服务器上匹配的key;通过一些特殊符号(通配符)来描述key的模样,匹配上述模样的key就可以被查询出来;

语法:

KEYS pattern
  • h?llo 匹配 hello , hallo 和 hxllo
  • h*llo 匹配 hllo 和 heeeello
  • h[ae]llo 匹配 hello 和 hallo 但不匹配 hillo
  • h[^e]llo 匹配 hallo , hbllo , ... 但不匹配 hello
  • h[a-b]llo 匹配 hallo 和 hbllo

时间复杂度:O(N)

返回值:匹配pattern的所有key

示例:

keys * 一个大“杀器”,查询Redis中所有的key;

注意:由于keys命令的时间复杂度是O(N),所有在真实的生产环境上,一般都会禁止使用keys*;因为生产环境上的key可能会非常的多,而redis是一个单线程的服务器,执行keys*的时间就会非常的长,就可能会使Redis的服务器被阻塞了,无法给客户端提供服务了;由于Redis经常会用于做缓存,挡在MySQL前面,而万一Redis被keys*阻塞了,此时其他查询Redis的操作就会超时,这些请求就会直接查询数据库;最终可能导致MySQL挂掉,整个服务器最后基本就瘫痪了。


EXISTS 

功能:判定某个key是否存在

语法:

EXISTS key [key ...]

时间复杂度:O(1)

返回值:key存在的个数

说明:

  • 这个命令针对查询多个key来说是非常有用的;
  • Redis组织这些key是按照哈希表的方式来组织的,所以时间复杂度是O(1)

示例:

上面两种执行命令的区别?

Redis只一个客户端服务器结构的程序,客户端和服务器之间通过网络来进行通信;分开写会产生多轮次的网络通信,而一起写只会有一次的网络通信,效率比较高,虽然结果是一样的;

DEL

功能:删除指定的key

语法:

DEL key [key ...]

时间复杂度:O(1)

返回值:删除掉的key的个数

示例:

说明:我们要联系Redis的定位用途,他是作为缓存来存放热点数据的,全量的数据是存放在MySQL中的;删除一个key一般来说问题不大;但是如果把所有的数据或者一大半数据删除了,这种影响会非常的大;因为这样容易把所有的请求打给MySQL,然后MySQL就会被搞挂;相比之下MySQL的全量数据哪怕误删一个数据影响都是很大的;


EXPIRE

功能:为指定的key添加秒级别的过期时间(Time To Live TTL)

语法:

EXPIRE key seconds

时间复杂度:O(1)

返回值:1 表⽰设置成功。0 表⽰设置失败。

示例:

说明:

这个命令 有很多的时间限制的业务场景的,例如:手机验证码(该验证码5分钟内有效)、外卖优惠券(该优惠券在指定的时间内有效)等等;


TTL

功能:获取指定 key 的过期时间,秒级

语法:

TTL key

时间复杂度:O(1)

返回值:剩余过期时间。-1 表⽰没有关联过期时间,-2 表⽰ key 不存在。

示例:

EXPIRE 和 TTL 命令都有对应的⽀持毫秒为单位的版本:PEXPIRE 和 PTTL,详细⽤法就不再
介绍了。

Redis的key的过期策略是怎么实现的?(经典面试题)

Redis整体策略是定期删除和惰性删除

  • 定期删除:每次抽取一部分,进行验证过期时间;保证抽取检查的过程足够快;
  • 惰性删除:假设这个key已经到过期的时间了,但是暂时还没有处理它,key还存在;紧接着后面又一次访问,正号用到了这个key,于是这次访问就会让Redis触发机制删除key的操作,同时在返回一个nil;

虽然有了上述两种策略结合整体效果一般,仍然可能会有很多过期的key被残留没有被即使删除;Redis为了对上述进行了补充,还提供了一系列的内存淘汰策略,我会在后面的文章中提到;


TYPE 

功能:返回key对应的数据类型

语法:

TYPE key

时间复杂度:O(1)

返回值:none , string , list , set , zset , hash and stream .

示例:

本篇文章只是抛砖引⽟,给出⼏个通⽤的命令,为 5 种数据结构的使⽤做⼀个热⾝,后续章节将对
键管理做⼀个更为详细的介绍。 

数据结构的内部编码

type 命令实际返回的就是当前键的数据结构类型,它们分别是:string(字符串)、list(列
表)、hash(哈希)、set(集合)、zset(有序集合),但这些只是 Redis 对外的数据结构

Redis的5中数据类型

实际上 Redis 针对每种数据结构都有⾃⼰的底层内部编码实现,⽽且是多种实现,这样 Redis 会
在合适的场景选择合适的内部编码

Redis数据结构和内部编码

可以看到每种数据结构都有⾄少两种以上的内部编码实现,例如 list 数据结构包含了 linkedlist 和
ziplist 两种内部编码。同时有些内部编码,例如 ziplist,可以作为多种数据结构的内部实现,可以通过 object encoding 命令查询内部编码:

可以看到 hello 对应值的内部编码是 embstr,键 mylist 对应值的内部编码是 ziplist。
Redis 这样设计有两个好处:

  1. 可以改进内部编码,⽽对外的数据结构和命令没有任何影响,这样⼀旦开发出更优秀的内部编码,⽆需改动外部数据结构和命令,例如 Redis 3.2 提供了 quicklist,结合了 ziplist 和 linkedlist 两者的优势,为列表类型提供了⼀种更为优秀的内部编码实现,⽽对⽤⼾来说基本⽆感知。
  2. 多种内部编码实现可以在不同场景下发挥各⾃的优势,例如 ziplist ⽐较节省内存,但是在列表元素⽐较多的情况下,性能会下降,这时候 Redis 会根据配置选项将列表类型的内部实现转换为linkedlist,整个过程⽤⼾同样⽆感知。 

单线程架构

Redis只是用一个线程来处理所有的命令请求,不是说一个Redis服务器进程内部真的只有一个线程,其实也有多个线程,多个线程是在 处理网络IO;

当有很多的客户端同时并发的对Redis服务器发起了请求;此时的服务器并不会因此而产生线程安全问题,因为Redis服务器实际上是采用单线程模型的,保证当前收到的多个请求是串行执行的;

多个请求同时到达Redis服务器时,也是要在队列中排队;再等待Redis服务器一个一个的取出里面的命令再执行;

Redis能够使用单线程模型很好的工作,原因主要在于Redis的核心业务逻辑都是短平快的,不太消耗CPU资源;

因此它的单线程模型也是它的缺点:使用Redis必须特别小心,某个操作占用时间太长,就会阻塞其他命令的执行;如果某个命令执⾏过⻓,会导致其他命令全部处于等待队列中,迟迟等不到响应,造成客⼾端的阻塞,对于 Redis 这种⾼性能的服务来说是⾮常严重的,所以 Redis 是⾯向快速执⾏场景的数据库

为什么单线程还能这么块?(经典面试题)

  1. 就如上面所说Redis核心功能,比其他数据库的核心功能更简单
  2. 纯内存访问。Redis 将所有数据放在内存中,内存的响应时⻓⼤约为 100 纳秒,这是 Redis 达到每秒万级别访问的重要基础。其他数据库是访问硬盘。
  3. 单线程避免了线程切换和竞态产⽣的消耗。单线程可以简化数据结构和算法的实现,让程序模型更简单;其次多线程避免了在线程竞争同⼀份共享数据时带来的切换和等待消耗。
  4. ⾮阻塞 IO。Redis 使⽤ epoll 作为 I/O 多路复⽤技术的实现,再加上 Redis ⾃⾝的事件处理模型将 epoll 中的连接、读写、关闭都转换为事件,不在⽹络 I/O 上浪费过多的时间;也就是再处理网络IO的时候使用了IO多路复用机制

今天对Redis常用命令、内部编码、单线程模型的分享到这就结束了,希望大家读完后有很大的收获,也可以在评论区点评文章中的内容和分享自己的看法;个人主页还有很多精彩的内容。您三连的支持就是我前进的动力,感谢大家的支持!!! 


http://www.ppmy.cn/embedded/92870.html

相关文章

计算机网络-CSP初赛知识点整理

历年真题 [2016-NOIP-普及-第3题] 以下不属于无线通信技术的是( ) A. 蓝牙 B. Wifi C. GPRS D. 以太网 [2015-NOIP-普及-第10题] FTP 可以用于( )。 A. 远程传输文件 B. 发送电子邮件 C. 浏览网页 D. 网上聊天 [2019-CSP-J-第1题] 中国的国家顶级域名是( ). A. .cn B. .ch C.…

视频美颜SDK与直播插件的实现原理及优化方案详解

今天,小编将深入探讨视频美颜SDK与直播插件的实现原理,并提供一些优化方案。 一、视频美颜SDK的实现原理 视频美颜SDK主要依赖于图像处理技术,借助实时滤镜、图像增强和人脸检测等算法,为用户提供动态的美颜效果。其核心实现原理…

大模型笔记5 Extractive QA任务评估

目录 Extractive QA任务评估 Extractive QA评测指标 precision, recall, f1 ROUGE 划分训练与评估数据集 token位置评估 单个token位置评估 输入label的token位置 预测token位置 评估 Wandb 共享机器同时登录 样本类别平衡 标记token label时对窗口进行筛选 训练…

JavaEE: 查看线程信息

示例用代码 public class Main {static class MyThread extends Thread {Overridepublic void run() {while (true) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}public st…

【ZooKeeper】ZooKeeper快速入门

1.ZooKeeper的概念 Zookeeper 是 Apache Hadoop 项目下的一个子项目,是一个树形目录服务。Zookeeper 翻译过来就是动物园管理员,它是用来管 Hadoop(大象)、Hive(蜜蜂)、Pig(小猪)的管…

如何在Chrome、Edge、360、Firefox等浏览器查看网站SSL证书信息?

在如今的网络环境中,保障网络安全、数据安全尤其重要,市面上大部分网站都部署了SSL证书以实现HTTPS加密保护数据传输安全以及验证网站身份,确保网站安全可信。那么如何查看网站的SSL证书信息?接下来,我们将详细介绍如何…

[算法]第一集 递归(未完待续)

递归啊递归,说简单简单,说难难。 首先我们要知道 一、什么是递归? 我们再C语言和数据结构里都用了不少递归,这里就不多详细介绍。 递归简单来说就是函数自己调用自己的情况 二、为什么要用递归呢? 本质来说其实就…

目标检测——GDXray数据集转为YOLO格式

关于该数据集的介绍可以看我写的另一篇博客:链接 论文题目:《GDXray: The Database of X-ray Images for Nondestructive Testing》论文链接:https://link.springer.com/article/10.1007/s10921-015-0315-7 Github链接: https:…