首页 > 数据库 >【Redis】全局命令/内部编码/浅谈单线程模型

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

时间:2024-08-04 21:53:23浏览次数:16  
标签:编码 浅谈 单线程 Redis 命令 key 数据结构

目录

前言

两个核心命令

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

标签:编码,浅谈,单线程,Redis,命令,key,数据结构
From: https://blog.csdn.net/qq_55119554/article/details/140906481

相关文章

  • redis通过滑动窗口实现限流
    一、什么是滑动窗口限流滑动窗口限流是一种流量控制策略,用于控制在一定时间内允许执行的操作数量或请求频率。它的工作方式类似于一个滑动时间窗口,对每个时间窗口的请求数量进行计数,并根据预先设置的限流策略来限制或调节流量,通常包括以下几个要素:时间窗口:限流的时间段,例如每秒、......
  • redis
    redis安装目录规划:###redis下载目录/data/soft/[###redis安装目录/opt/redis_cluster/redis{PORT}/{conf,logs,pid}###redis数据目录/data/redis_cluster/redis{PORT}/redis{PORT}.rdb###redis运维脚本/root/scripts/redisshell.sh安装命令:编辑hosts......
  • 模拟实现 srtcat(字符串追加) --浅谈C语言
    strcat描述char*strcat(char*dest,constchar*src)把src所指向的字符串追加到dest所指向的字符串的结尾。声明下面是strcat()函数的声明。char*strcat(char*dest,constchar*src)参数dest--指向目标数组,该数组包含了一个C字符串,且足够容纳追加后的字符......
  • 位段 -- 内存布局详解-浅谈C语言
    目录位段位段的介绍位段使用示例:位段的内存分配Example内存分配解析:位段的跨平台问题位段位段的介绍位段(二进制位):就是按位存储位段(bit-field)是C语言中的一种特殊数据类型,它允许将一个字节分成几个部分,并为每个部分指定特定的位数,以便在内存中存储和访问这些部分。其中位......
  • redis+xxl-job初步设计点赞功能
    一般情况下点赞业务涉及以下下几个方面:1.我们肯定要知道一个题目被多少人点过赞,还要知道,每个人他点赞了哪些题目。2.点赞的业务特性,频繁。用户一多,时时刻刻都在进行点赞,收藏等等处理,如果说我们采取传统的数据库的模式啊,这个交互量是非常大的,很难去抗住这个并发问题,所以我们......
  • Redis 批量删除键
    Redis批量删除键1.简介在Redis中批量优雅的删除大量键是一个很麻烦的问题,下面例举常用的方法和优缺点。2.keys+del命令使用keys使用查找所有匹配的键,然后在使用del一起批量删除。优点操作简单。缺点查找性能特别差,需要遍历所有键。如果rediskey特别多,还有可能造......
  • 【Redis 进阶】哨兵 Sentinel(重点理解流程和原理)
    Redis的主从复制模式下,一旦主节点由于故障不能提供服务,需要人工进行主从切换,同时大量的客户端需要被通知切换到新的主节点上,对于上了一定规模的应用来说,这种方案是无法接受的,于是Redis从2.8开始提供了RedisSentinel(哨兵)加个来解决这个问题。一、基本概念由于对Red......
  • redis缓存雪崩
    Redis缓存雪崩是指在短时间内大量缓存数据同时失效,导致原本应该由缓存承担的请求流量突然涌向后端数据库或其他数据源,从而给后端系统带来巨大压力,可能导致数据库超负荷甚至崩溃的现象。 缓存雪崩通常发生在以下几种情况:-大量数据设置了相同的过期时间,在同一时刻失效。-......
  • Redis - Smembers性能优化
    命令概述SMembers命令用于获取一个集合的所有成员。它的语法如下:SMEMBERSkey其中,key是集合的名称。SMembers命令返回一个包含所有集合成员的数组。如果集合不存在,返回空数组。关键因素内存占用:Redis是内存数据库,因此集合的大小直接影响到内存使用量。网络传输:当使用S......
  • Java通过redis实线多线程多用户操作时添加锁
    背景由于项目中多出涉及同步数据,同步过程就是从设备上查询数据,将数据库中该设备数据删除,将新数据导入到数据库;多次同步数据或多用户操作,会导致数据库出现重复数据,例如,两个线程同时删除设备数据,同时导入数据,就会出现双倍数据;还有线程1正在导入数据,中途线程2将线程1导入数据之前删......