当前位置: 首页 > article >正文

[Redis][预备知识]详细讲解

目录

  • 1.命令
    • 1.最核心的两个命令
      • 1.SET
      • 2.GET
      • 3.说明
    • 2.基本全局命令
      • 0.前言
      • 1.KEYS
      • 2.EXISTS
      • 3.DEL
      • 4.EXPIRE
      • 5.TTL
      • 6.TYPE
  • 2.数据结构和内部编码
  • 3.单线程架构
    • 1.单线程模型
    • 2.单线程还效率高?(重点)
    • 3.注意


1.命令

1.最核心的两个命令

1.SET

  • 语法SET key value
  • 功能:设置key以保存字符串value
    • 如果key已持有一个值,则无论其类型如何,它都会被覆盖
    • 在成功的SET操作中,将与密钥关联的任何先前生存时间都被丢弃

2.GET

  • 语法GET key
  • 功能:获取key的值
    • 如果键不存在,则返回特殊值nil -> 和NULL一个意思
    • 如果存储在key处的值不是字符串,则返回错误,因为GET仅处理字符串值

3.说明

  • Redis中,命令是不区分大小写的
  • 上述的KeyValue,不需要加上引号,就是字符串类型
    • 如果加上引号(单双引号都行),也没问题

2.基本全局命令

0.前言

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

1.KEYS

  • 语法KEYS pattern
  • 功能:返回满足所有样式(pattern)的key
  • 支持的通配符样式如下
    • ?:匹配一个字符
    • *:匹配任意多个字符
    • [ab]:只能匹配括号内的字符,此处为只能匹配a b
    • [^a]:排除括号内的字符,此处为只有a匹配不了,其他都能匹配
    • [a-b]:匹配a - b这个范围内的字符,包含两侧边界
  • 返回值:匹配pattern的所有key
  • 注意:时间复杂度 O ( N ) O(N) O(N),在生产环境上,一般都会禁用KEYS命令,尤其是KEYS *
    • 生产环境上的key可能会非常多,而Redis是一个单线程服务器,执行KEYS *的时间非常长,就会使Redis服务器被阻塞,无法给其他客户端提供服务
    • 此时其他的查询Redis操作超时了,就直接会去查数据库,突然一大波数据突然来了,MySQL可能措手不及,就直接挂了

2.EXISTS

  • 语法EXISTS key [key...]
  • 功能:判断某个key是否存在
  • 返回值key存在的个数
    • 针对多个key而言,是非常有用的
  • 时间复杂度 O ( 1 ) O(1) O(1)
  • EXISTS key1 key2和分开写EXISTS key1EXISTS key2有什么区别?
    • 分开的写法,会产生更多的轮次的网络通信
    • 此时跟直接操作内存相比,效率比较低,成本比较高

3.DEL

  • 语法DEL key [key...]
  • 功能:删除指定的key
  • 返回值:删除掉的key的个数
  • 时间复杂度 O ( 1 ) O(1) O(1)
  • Redis 的删除操作没有像MySQL那样危险,但依然要小心
    • Redis的主要应用场景是缓存,并且存的都是热点数据
      • 如果只是误删了几个数据,一般来说,问题不大
      • 但是如果一下误删了一大半,此时影响还是会很大,因为Redis本是帮MySQL负重前行,但此时Redis没数据了,大部分的请求就直接打给MySQL了,此时就很容器把MySQL搞挂
      • 相比之下,如果是MySQL这样的数据,哪怕误删一个,问题都可能很大
    • Redis如果作为数据库,那误删的数据影响就肯定很大了
    • Redis如果作为消息队列,此时的影响,就要具体分析了

4.EXPIRE

  • 语法EXPIRE key seconds
  • 功能:为指定的key添加秒级的过期时间(Time To Live TTL)
    • 毫秒单位版本PEXPIRE
  • 返回值:1表⽰设置成功,0表⽰设置失败
  • 时间复杂度 O ( 1 ) O(1) O(1)

5.TTL

  • 语法TTL key
  • 功能:获取指定key的过期时间,秒级
    • 毫秒单位版本PTTL
  • 返回值:剩余过期时间,-1表⽰没有关联过期时间,-2表⽰key不存在
  • 时间复杂度 O ( 1 ) O(1) O(1)
  • 键过期机制:定期删除 + 惰性删除 + 内存淘汰策略
    • 惰性删除:一个key已经过期,但是暂时还没删除,此时key还存在,后面来了一个访问,正好用到了这个key,此时该访问就会让Redis服务器触发删除key的操作
    • 定期删除:每次抽取一部分,进行验证过期时间,保证这个抽取检查的过程足够快
      • 因为Redis是单线程程序,如果扫描过期key消耗的时间太多了,会导致其他正常处理请求命令被阻塞
        请添加图片描述

6.TYPE

  • 语法TYPE key
  • 功能:返回key对应的value的数据类型
  • 返回值none, string, list, set, zset, hash, stream
  • 时间复杂度 O ( 1 ) O(1) O(1)

2.数据结构和内部编码

  • TYPE命令实际返回的就是当前键的数据结构类型,但这些只是Redis对外的数据结构

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

  • 可以通过object encoding key来查看对应的value的实际编码方式

  • Redis这样设计的好处

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

3.单线程架构

1.单线程模型

  • Redis只使用一个线程处理所有的请求,但并不代表Redis服务器进程内部真的就只有一个线程

    • 事实上,Redis内部也有多个线程,多个线程都是在处理网络IO
  • Redis采⽤单线程模型执⾏命令的是指:虽然以下三个客⼾端看起来是同时要求Redis去执⾏命令的,但微观⻆度,这些命令还是采⽤线性⽅式去执⾏的,只是原则上命令的执⾏顺序是不确定的,但⼀定不会有两条命令被同步执⾏
    请添加图片描述

  • 感性理解

    • 虽然多个客户端是"并发"的发起了请求,但是Redis实际上处理请求时是单线程模型,保证了当前收到的多个请求,在Redis内部,依然是串行执行的
    • 多个请求同时到达Redis服务器,也要先在队列中排队,再等待Redis服务器一个一个地取出里面的命令再执行
  • Redis采用单线程模型地原因:Redis核心业务逻辑都是短平快的,不太消耗CPU资源,也就不太吃多核

  • 注意:正因为Redis是单线程模型,所以要特别小心,如果某个操作占用时间长,就会阻塞其他命令的执行


2.单线程还效率高?(重点)

  • 首先明确,说Redis快,是以数据库为参照的,没有参照,单纯说快,就是耍流氓 😛
  • Redis纯内存访问,数据库则是访问硬盘
  • Redis核心功能,比数据库的核心功能简单
  • 单线程模型,避免了一些不必要的线程竞争开销
    • Redis每个基本操作,都是短平快的,简单操作一下内存,并不是很消耗CPU,即使搞了多线程,提升也不大
    • 单线程可以简化数据结构和算法的实现,
  • 处理网络IO地时候,使用了epoll这样的IO多路复用机制 --> 非阻塞IO
    请添加图片描述

3.注意

  • Redis有⼀个致命的问题对于单个命令的执⾏时间都是有要求的
    • 如果某个命令执⾏过⻓,会导致其他命令全部处于等待队列中,迟迟等不到响应,造成客⼾端的阻塞,对于Redis这种⾼性能的服务来说是⾮常严重的
    • 所以Redis是⾯向快速执⾏场景的数据库

http://www.kler.cn/news/316207.html

相关文章:

  • Hive企业级调优[1]——计算资源配置
  • 照片写真记录摄影作品记录网站源码
  • setup.py详解 及 pip install用法
  • 【QT开发-Pyside】使用Pycharm与conda配置Pyside环境并新建工程
  • 如何在 Qt 的 QListWidget 中为某一行添加点击事件
  • Oracle数据库中什么情况下需要使用游标
  • 微信小程序拨打电话点取消报错“errMsg“:“makePhoneCall:fail cancel“
  • Go-知识recover
  • JbossMQ反序列化漏洞CVE-2017-7504
  • WPF 异步
  • Qt 注册表操作
  • 数据结构--顺序表的创建和增删改查操作
  • windows docker下启动mysql报Bind on unix socket: Input/output error
  • Nginx越界读取缓存漏洞(CVE-2017-7529)
  • 【ShuQiHere】 探索数据挖掘的世界:从概念到应用
  • c++中std::find()函数
  • 【测试】——Selenium API (万字详解)
  • 【dom操作基础】案例题1
  • Ubuntu24.04中安装Electron
  • 8. 防火墙
  • JAVA并发编程系列(8)CountDownLatch核心原理
  • 基于等保2.0标准——区块链安全扩展要求探讨
  • git 介绍+常用命令
  • LeetCode 2374.边积分最高的节点:模拟
  • Git 推送更改到远程仓库
  • 什么是量化交易,纸质股票现在还能交易吗?怎么交易
  • 基于机器学习的注意力缺陷/多动障碍 (ADHD)(python论文+代码)HYPERAKTIV
  • 路径处理 | 关键点提取之Douglas–Peucker算法(附ROS C++/Python实现)
  • 分布式锁的几种方案对比?你了解多少种呢?
  • vscode关闭git的提交提示