Redis系列---数据管理

ops/2024/11/1 11:41:36/

目录标题

  • 数据类型
    • String
      • 优点
      • 缺点
      • 底层结构
      • 使用场景
      • 实际使用
    • List
      • 优点
      • 缺点
      • 底层结构
      • 使用场景
      • 实际使用
    • Hash
      • 优点
      • 缺点
      • 底层结构
      • 使用场景
      • 实际使用
    • Set
      • 优点
      • 缺点
      • 底层结构
      • 使用场景
      • 实际使用
    • Zset
      • 优点
      • 缺点
      • 底层结构
      • 使用场景
      • 实际使用
    • BitMap
    • Stream
  • 类型抉择
  • 空间占用
  • 数据特征
  • 数据删除策略
    • 定时删除
    • 惰性删除
    • 定期删除
  • 数据淘汰策略

数据类型

redis中value的最大容量默认是 512M,各个数据类型初始容量如下:

  1. String:512M
  2. Set,ZSet,List,Hash:2^32 -1 个元素

总结:任何系统都是在内存和性能之间不断抉择,使用最少的内存提供可接受的反应速度。redis亦如此。

String

优点

简单直观,便捷存储单个元素/散列元素。提供字符串函数,append等

缺点

占用过多的键,内存占用量较大,同时用户信息内聚性比较差。难以管理

底层结构

简单动态字符串(simple dynamic string),字节数组+未用空间+已用空间,预分配空间,方便快速扩容及确定字段长度,牺牲空间换时间

使用场景

可以存储任意类型的数据,包括文本、数字等。

实际使用

  • 热点用户个人信息
  • 库存计数器
  • 分布式锁
  • 项目奖品策略
  • 广告点击次数
  • 验证码

List

优点

存储有序数据,支持从列表的两端进行元素的插入和删除操作。

缺点

数据耦合高,取内部元素相对耗时

底层结构

老版本是双向链表+压缩列表,双向链表即pre+value+next,压缩链表即分配一段连续内存,省掉pre和next的损耗,前者适合大量元素,后者适合少量元素;

新版本采用快速链表,是前两者的融合,pre+小型双向链表+next,即将长度较大的双向链表进行分段存储。

  • 压缩列表ziplist (插入元素过多或字符串太大,就需要调用 realloc 扩展内存 )
  • 双向链表linkedlist (需附加指针prev 和 next,较浪费空间,加重内存的碎片化 )

因为双向链表占用的内存比压缩列表要多,所以当创建新列表时,会优先考虑使用压缩列表,并且在有需要的时候才从压缩列表实现转换到双向链表实现。

压缩列表转化成双向链表条件有两个:

  • 列表中某个字符串值超过 list_max_ziplist_value(默认64字节 )
  • 列表的元素个数超过 list_max_ziplist_entries(默认 512个 )

使用场景

有序消息,或者固定容量数据。例如消息队列、最新消息排行

实际使用

消息队列虽然可以但不建议因为redis会丢消息,它是缓存不是持久存储,除非是不重要的消息

  • 广告展示,默认展示最新条数,设置长度固定的list,每次从顶端插入,从尾端剔除元素;
  • 中奖名单,同样固定容量,顶端插入提出尾部元素。

Hash

优点

通过一个key对应多个字段和对应的值,适用于存储对象属性、配置信息等复杂数据结构。

缺点

数据占用空间过大时增删耗时旧,甚至引起reids卡顿

底层结构

压缩列表+hashtable,与list的压缩列表不同的是,它存储的不仅是feild+value交替存储;hashtable即java的hashmap,数组+链表。
渐进式扩容:新老hashtable交替执行,即旧数据慢慢同步至新hashtable中。

新建hash值时优先使用压缩列表实现,压缩列表使用更加紧凑的连续内存结构可以节省空间,其读写复杂度为O(n);当数据量过大或者字段过多读写效率减低,此时会转化为hashtable,占用更多的内存,读写复杂度降低为O(1)。转化条件:

  • 哈希类型元素个数大于hash-max-ziplist-entries配置(默认512个)
  • 有字段值大于hash-max-ziplist-value配置(默认64字节)

使用场景

总是需要获取单一属性的值,数据既耦合又方便存取。

实际使用

  • 地理位置信息对应关系
  • 项目配置信息

Set

优点

无序集合,可以存储多个字符串元素,并提供高效的集合操作,如交集、并集、差集等。

缺点

大量数据会导致redis卡顿

底层结构

intset+hashTable;采用hashTable存储,只是value统一设置为null,为什么不用ziplist来节省空间是因为必须保证元素的唯一性。

inset可理解为数组,使用intset存储必须满足下面两个条件,否则使用hashtable,条件如下:

  • 对象保存的所有元素都是整数值(int)
  • 对象保存的元素数量不超过512个

使用场景

需要进行集合运算的数据。

  • 例如文章标签管理-可根据多个标签聚合查询文章;
  • 社交网络好友关系-将每个用户的好友列表存储在Redis的集合中,使用集合操作可以快速判断两个用户是否是好友,还可以进行好友推荐等功能。

实际使用

  • 经销商的门店服务列表,业务员可以交叉负责经销商底下的门店,利用经销商和门店的归属关系可以去重聚合出经销商的门店列表;
  • 策略集聚合,一个转盘会对应多个策略集,通过条件判断出新老用户概念,确定出需要聚合哪些的策略。

Zset

优点

存储多个字符串元素,并为每个元素关联一个分数,支持按照分数进行排序和范围查找。

缺点

  • 内存开销:Zset是基于跳表和哈希表实现的,存储数据时,会占用比简单的集合或列表更多的内存。因此,在存储较大规模的数据时,内存开销可能会显著增加。

  • 性能开销:在一些特定操作中,如按得分范围查询(ZRANGEBYSCORE)或根据排名进行范围查询(ZRANGE),操作的复杂度为O(log(N) + M),其中N是集合的大小,而M是返回的小集合大小。这与其他类型的数据结构相比,可能在性能上有所逊色,尤其是在处理大数据量时。

  • 数据排序:虽然Zset提供了自动排序功能,但在某些情况下(如频繁更新得分),这可能导致性能下降,尤其是在需要多次更新和读取的场景下。

底层结构

hashtable+skiplsit,hashtable存储k-score, skiplist中的每个node存储 层级+value+score,插入时按照score排序。

当元素数量不多时,hashtable和SkipList的优势不明显,而且更耗内存。因此zset还会采用ZipList结构来节省内存。

查询效率和红黑树相当。

使用场景

需要排序的数据

实际使用

业务员的补货数量排名。

BitMap

Bitmap数据类型可以看作是一种特殊的字符串,它所占用空间中的每一个bit都只能是0或1。Redis内部将每个字符(bit)作为一个元素来处理,因此我们可以在非常小的空间中存储大量的位信息。这使得Bitmap非常适合于存储和处理大规模的布尔型信息,如用户的在线状态、活跃用户、用户访问记录等。

统计消费者的参与情况,和业务员的工作情况。

Stream

Redis Stream 是 Redis 5.0 版本新增加的数据结构。

Redis Stream 主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。

类型抉择

  • 多个集合操作(聚合操作)----用Set;
  • 集合数据排序(排序操作) ---- 分页排序建议使用ZSet;
  • 集合数据只有0、1两种状态(二值型数据)----------- 0/1状态数据建议使用Bitmap;
  • 集合中不重复元素个数(基数统计)----如果数据量达到亿级的话建议使用HyperLogLog。

当然以上都是套话,任何抉择都一样,搞清楚自己的需求,对症下药即可,当你对各种数据类型的特性了解之后,自然就可以做出最正确的选择。何时何地何事都如此。

空间占用

以String类型计算,k是tc:jdb:/UZJXTIP0CTZ6L0 v是32010670;

  • 2.4kw 5G
  • 1ww 25G

总结起来就是 1个kv占用218B。而在计算机中,一个英文字母/整数通常占用1个字节(1 B)。这是因为在使用 ASCII 编码时,单个英文字母(无论是大写还是小写)或者整数都可以用一个字节表示。

所以redis的空间占用大概是字节数的7倍。

数据特征

Redis是一种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过TTL指令获取其状态。TTL返回的值有三种情况:正数,-1,-2

  • 正数:代表该数据在内存中还能存活的时间
  • -1:永久有效的数据
  • -2:已经过期的数据 或被删除的数据 或 未定义的数据

redis中的过期时间是单独存储的,Hash结构,field是内存地址,value是过期时间,保存了所有key的过期描述,在最终进行过期处理的时候,对该空间的数据进行检测, 当时间到期之后通过field找到内存该地址处的数据,然后进行相关操作。

在这里插入图片描述

数据删除策略

删除策略就是针对已过期数据的处理策略,已过期的数据是真的就立即删除了吗?其实并不是,redis有多种删除策略,在不同的场景下使用不同的删除方式会有不同效果。

不同的删除策略就是对内存占用与CPU占用之间的不同侧重。目前有三种删除策略:

  1. 定时删除:时间换空间,通过对cpu的无间断占用节约内存
  2. 惰性删除:空间换时间,通过对内存的占用节约cpu资源
  3. 定期删除:折中方案,花费少量cpu资源节约少量内存

定时删除

创建一个定时器,当key设置有过期时间,且过期时间到达时,由定时器任务立即执行对键的删除操作
在这里插入图片描述

惰性删除

数据到达过期时间,不做处理,等该数据被访问时进行过期判断。如果未过期,直接返回数据,如果已过期,先删除数据,再返回数据不存在
在这里插入图片描述

定期删除

定时删除和惰性删除这两种方案都是走的极端,那有没有折中方案?是的,redis还引入了一种定期删除策略,进行了空间和性能的折中处理

已知redis 会将每个设置了过期时间的 key 放入到一个独立的字典中,该方案是默认每秒进行十次过期扫描(100ms一次),过期扫描不会遍历过期字典中所有的 key,而是采用了一种简单的贪心策略。

  • 从过期字典中随机 20 个 key;
  • 删除这 20 个 key 中已经过期的 key;
  • 如果过期的 key 比率超过 1/4,那就重复步骤 1;

数据淘汰策略


http://www.ppmy.cn/ops/130122.html

相关文章

使用web.dev提供的工具实现浏览器消息推送服务

文章目录 前言实现工具和效果实现原理实现过程前端接收用户订阅请求将用户订阅信息更新到后端后端实现接收并保存订阅信息的接口后端实现消息推送的逻辑前言 对于电商独立站来说,新品上架或者促销活动上线及时通知到用户是很重要的,通知的渠道有很多,其中就包括浏览器消息推…

吉林大学2023级数据结构上机实验第(1~2周)参考答案(关注我,在系统关闭后持续更新)

A 括号匹配&#xff08;进阶版&#xff09; 分数 10 编写程序检查给定字符串中包含的括号是否正确匹配&#xff0c;本题中的括号有{ }、[ ]、( )、< >四种。另外再加上一个新的约束条件&#xff1a;当有多种括号嵌套时&#xff0c;嵌套的顺序应为{ → [ → ( → <&…

pytest高版本兼容test_data[“log“] = _handle_ansi(“\n“.join(logs))错误

一、问题现象&#xff1a; 执行seleniumpytest结束时报: INTERNALERROR> File "D:\workspace\pytestframe\.venv\Lib\site-packages\pytest_html\report_data.py", line 141, in add_test INTERNALERROR> test_data["log"] _handle_ansi(&q…

Webserver(2.6)有名管道

目录 有名管道有名管道使用有名管道的注意事项读写特性有名管道实现简单版聊天功能拓展&#xff1a;如何解决聊天过程的阻塞 有名管道 可以用在没有关系的进程之间&#xff0c;进行通信 有名管道使用 通过命令创建有名管道 mkfifo 名字 通过函数创建有名管道 int mkfifo …

超子物联网HAL库笔记:准备篇

超子物联网 HAL库学习 汇总入口&#xff1a; 超子物联网HAL库笔记&#xff1a;[汇总] 写作不易&#xff0c;如果您觉得写的不错&#xff0c;欢迎给博主来一波点赞、收藏~让博主更有动力吧&#xff01; 1. HAL库简介 HAL库 HAL库&#xff08;Hardware Abstraction Layer&#…

采用STM32CubeMX和HAL库的模数转换器应用实例

目录 STM32的ADC配置流程 模/数&#xff08;A/D&#xff09;转换器应用的硬件设计 模/数&#xff08;A/D&#xff09;转换器应用的软件设计 1. 通过STM32CubeMX新建工程 2. 通过Keil MDK实现工程 STM32的ADC功能繁多&#xff0c;比较基础实用的是单通道采集&#xff0c;实…

统信UOS适配C#

通过Mono或.NET Core等运行时,在UOS上进行C#应用开发、编译、调试及部署变得便捷。 文章目录 一、环境部署1. C#开发环境安装2. C#开发环境配置二、 C#开发案例三、常见问题1. 图形界面支持2. 调试工具一、环境部署 1. C#开发环境安装 统信UOS V20使用dotnet 7.0 amd64版本,…

springboot框架使用RabbitMQ举例代码

以前分享过一个理论有兴趣的小伙伴可以看下 https://blog.csdn.net/Drug_/article/details/138164180 不多说 还是直接上代码 第一步&#xff1a;引入依赖 可以不指定版本 <!-- amqp --><dependency><groupId>org.springframework.boot</groupId…