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

Redis系列---数据管理

目录标题

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

数据类型

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结构来节省内存。

查询效率和红黑树相当。

使用场景

需要排序的数据

实际使用

业务员的补货数量排名。

HyperLogLog

优点

在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。

缺点

HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。

底层结构

类似于java的set

使用场景

比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。

实际使用

需要用set的地方都可以使用

GEO

优点

进行坐标计算

缺点

相较于一些专门的地理空间数据库(如 PostGIS),Redis Geo 的地理空间索引功能较为基本,可能不适合需要复杂空间分析的应用。

底层结构

有序集合(Sorted Set):Redis 使用有序集合来存储地理位置数据,每个地理位置由一个成员(通常是地点的名称或标识符)和对应的分值(经纬度信息)组成。分值是通过将经纬度转化为一个可以唯一标识该点的整数值。

使用场景

地理位置计算

实际使用

附近门店功能

Stream

简介

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

使用场景

在处理可丢失的信息时可以采用该方式,但一定要配合兜底的定时任务,防止消息丢失后完全处理失败。

实际使用

入金后修改只读账号状态

BitMap

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

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

类型抉择

  • 多个集合操作(聚合操作)----用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.kler.cn/a/378699.html

相关文章:

  • 操作系统(10) (并发(2)------基于软件/硬件/操作系统层面解决两个进程之间的临界区问题/抢占式/非抢占式内核)
  • 深入学习 Scrapy 框架:从入门到精通的全面指南
  • C++ 编程基础(4)函数 | 4.1、函数概述
  • 分享一些做事的原则
  • channel error 报错【已解决】
  • C++和OpenGL实现3D游戏编程【连载17】——着色器进阶(附源码)
  • git入门教程8:git高级分支管理
  • YOLO11论文 | 重要性能衡量指标、训练结果评价及分析及影响mAP的因素【发论文关注的指标】
  • Docker Swarm集群配置与使用
  • 基于知识中台的智能法律咨询服务:革新法律服务的新篇章
  • sicp每日一题[2.65]
  • 【D3.js in Action 3 精译_039】4.3 D3 面积图的绘制方法及其边界标签的添加
  • RTP和RTCP的详细介绍及其C代码示例
  • UG NX二次开发(C#)-UFun-创建草图和草图曲线
  • Redis设计与实现 学习笔记 第十四章 服务器
  • RSTP的工作过程
  • CentOS 9 Stream 上安装 Redis
  • 从事人工智能相关岗位需要具备哪些技能?
  • 交叉编译工具链命名规则、以及如何生成交叉编译工具链步骤
  • bash: git: command not found
  • SpringBoot源码(四):run() 方法解析(一)
  • 微服务架构面试内容整理-微服务与传统单体架构的区别
  • 在麒麟V10上下载pycharm
  • Pinctrl子系统中client端设备树相关数据结构介绍和解析
  • 【双目视觉标定】——1原理与实践
  • XSS跨站脚本攻击的实现原理及讲解