likes
comments
collection
share

【Redis】常见数据类型

作者站长头像
站长
· 阅读数 22

常见数据类型

  • 最基本的5种:String(字符串),Hash(哈希),List(列表),Set(集合)、Zset(有序集合)。
  • 新版本:BitMap(2.2)、HyperLogLog(2.8)、GEO(3.2)、Stream(5.0)。

String

组成:string、int、float,最长512MB

数据结构

  • int:编码整数

  • SDS简单动态字符串:编码raw、embstr

    • 界限:

      • redis 2.+:32 字节

      • redis 3.0-4.0:39 字节

      • redis 5.0:44 字节

【Redis】常见数据类型

Why?🤔

  • embstr一次内存分配一块连续的内存空间来保存redisObject和SDS,raw两次内存分配

【Redis】常见数据类型

【Redis】常见数据类型

应用场景

  • 缓存对象

    • 缓存json:SET user:1 '{"name":"xiaolin", "age":18}'
    • 分离字段缓存(user:ID:字段):MSET user:1:name xiaolin user:1:age 18 user:2:name xiaomei user:2:age 20
  • 常规计数:利用其原子性加减对计算访问次数、点赞、转发、库存数量等进行计数

  • 分布式锁:

    • NX参数:不存在才插入

      • key 不存在,则显示插入成功,表示加锁成功
      • key 存在,则会显示插入失败,表示加锁失败
    • 加锁:SET lock_key unique_value NX PX 10000

      • lock_key:key 键;
      • unique_value:客户端生成的唯一的标识;
      • NX:只在 lock_key 不存在时,才对 lock_key 进行设置操作;
      • PX 10000:设置 lock_key 的过期时间为 10s,避免客户端发生异常无法释放锁。
    • 解锁:将 lock_key 键删除,保证执行操作的客户端就是加锁的客户端。

      • Lua 脚本来保证解锁的原子性
      • -- 释放锁时,先比较 unique_value 是否相等,避免锁的误释放
        if redis.call("get",KEYS[1]) == ARGV[1] then
        return redis.call("del",KEYS[1])
        else
        return 0
        end
        
  • 共享 Session 信息

    • 所有应用服务器把session存储在redis,实现跨服务器读取

List

组成:双向链表

数据结构

  • Redis 3.2 版本前:

    • 压缩列表:列表的元素个数小于 512 个 & 列表每个元素的值都小于 64 字节
    • 双向链表
  • Redis 3.2 版本后:

    • quicklist

应用场景

  • 消息队列

    • 需求:

      • 消息保序:生产者LPUSH,消费者RPOP(可阻塞BRPOP)
      • 处理重复的消息:生产者为每个消息加一个全局 ID,消费者可避免重复消费
      • 可靠性:BRPOPLPUSH,读取后还有备份,避免处理失败数据丢失
    • 缺点:不支持多个消费者消费同一条消息

Hash

组成:key - value 集合

  • value=[{field1,value1},...{fieldN,valueN}]

数据结构

  • Redis 7.0 前:

    • 压缩列表:哈希类型元素个数小于 512 个 & 所有值小于 64 字节
    • 哈希表:其他情况
  • Redis 7.0 后:

    • listpack替换压缩列表

应用场景

  • 缓存对象:HMSET uid:1 name Tom age 15

    • 一般使用String + Json,当字段变化频繁使用Hash

Set

组成:无序并唯一的集合

数据结构

  • 整数集合:元素都是整数且元素个数小于 512
  • 哈希表:不满足上面条件

应用场景

  • 数据去重,保障数据的唯一性

    • 点赞
    • 共同关注
    • 抽奖活动
  • 统计多个集合的交集、错集和并集等

    • 缺点:计数复杂度高

Zset

组成:有序集合,元素值+排序值

数据结构

  • Redis 7.0 前:

    • 压缩列表:元素个数小于 128 个 & 每个元素的值小于 64 字节
    • 跳表:其他情况
  • Redis 7.0 后:

    • listpack替换压缩列表

应用场景

  • 对需要展示最新列表、排行榜等场景

    • 排行榜
    • 电话、姓名排序
  • 数据更新频繁或者需要分页显示

BitMap

组成:一串连续的二进制数组

数据结构

  • String,bit数组

应用场景

  • 二值状态统计

    • 签到统计
    • 判断用户登陆态

HyperLogLog

用于「统计基数」的数据集合类型,基数统计就是指统计一个集合中不重复的元素个数,标准误算率是 0.81%。

  • 只需要花费 12 KB 内存,就可以计算接近 2^64 个元素的基数

应用场景

  • 百万级网页 UV 计数

    • 计数:PFADD page1:uv user1 user2 user3 user4 user5

    • 统计:PFCOUNT page1:uv

GEO

存储地理位置信息

数据结构

直接使用了 Sorted Set 集合类型

  • GeoHash 编码方法实现了经纬度到 Sorted Set 中元素权重分数的转换、

    • 对二维地图做区间划分
    • 对区间进行编码

应用场景

  • 滴滴叫车:

    • 记录车位置:GEOADD cars:locations 116.034579 39.030452 33

    • 用户读取附近的车:GEORADIUS cars:locations 116.054579 39.030452 5 km ASC COUNT 10

Stream

Why?

  • 发布订阅模式,不能持久化
  • 不能读取历史消息
  • 不能重复消费

What?

专门为消息队列设计的数据类型,支持消息的持久化、支持自动生成全局唯一 ID、支持 ack 确认消息的模式、支持消费组模式等

应用场景

  • 消息队列

    • 消息保序:XADD/XREAD
    • 阻塞读取:XREAD block
    • 重复消息处理:Stream 在使用 XADD 命令,会自动生成全局唯一 ID;
    • 消息可靠性:内部使用 PENDING List 自动保存消息,使用 XPENDING 命令查看消费组已经读取但是未被确认的消息,消费者使用 XACK 确认消息;
    • 支持消费组形式消费数据
  • 与专业的消息队列的差距:

    • 会丢消息:

    • 消息可堆积性差

      • 消息积压时,如果指定了最大长度,队列长度超过上限后,旧消息会被删除。

Redis 发布/订阅机制为什么不可以作为消息队列?

  1. 没有基于任何数据类型实现,所以不具备「数据持久化」的能力,不会写入到 RDB 和 AOF 中,当 Redis 宕机重启,发布/订阅机制的数据也会全部丢失。
  2. 发布订阅模式是“发后既忘”的工作模式,如果有订阅者离线重连之后不能消费之前的历史消息。
  3. 当消费端有一定的消息积压时,也就是生产者发送的消息,消费者消费不过来时,如果超过 32M 或者是 60s 内持续保持在 8M 以上,消费端会被强行断开,这个参数是在配置文件中设置的,默认值是 client-output-buffer-limit pubsub 32mb 8mb 60
转载自:https://juejin.cn/post/7232272098755395644
评论
请登录