没长正的技术专栏 勤动手、多思考

Redis数据类型

2014-01-06

阅读:

2020-11-21

1. 数据类型

String、Hash、List、Set、Zset、BitMaps、Hyperloglogs、Geo、Streams ….

Redis底层基于C语言实现。

1.1 String

1.1.1 存储类型

底层存储: int、float、String …

1.1.2 底层编码

编码方式:int(存储8字节长整型)、embstr(SDS格式:存储小于44字节的字符串)、raw(储存大于44字节的字符串)

1.1.3 应用场景
  • 缓存热点数据
  • 分布式数据共享(服务集群不会出现数据不一致情况)
  • 分布式锁:setnx方法
    • redis分布式锁自动延长过期时间
    • 聊聊redis分布式锁的8大坑
      • 非原子操作

        setnx 与 expire 两个操作分开了

      • 忘了释放锁
      • 释放了别人的锁
      • 大量请求失败(都同时竞争1把锁,成均匀秒杀)

        =》分段、while(ture)自旋

      • 锁重入问题 =》使用可重入锁(redission框架=》Lua脚本实现)
      • 锁竞争问题(读、写)
      • 锁超时问题(watchdog:看门狗,定时续期,需要有总时间,不能无线续约)
      • 主从复制问题 (RedissonRedLock =》 大部分加锁成功,则加锁成功。(用的少,CP:zookeeper,AP:redis)
  • 全局ID
    • INT类型,INCRBY, 利用原子性
    • 分库分表场景(一次获取一段,每段新增/获取不同的ID)
  • 计数器
    • INT类型,INCRBY, 利用原子性
      • 文章阅读量、点赞数(允许一定的延迟、先写入redis,再定时同步到mysql)
    • 限流
      • 以访问者IP或其他信息作为KEY,访问一次增加1,超过次数,则返回false

如果一个对象有多个值,需要存储,应该怎么办?

1.2 Hash

1.2.1 存储类型

用来存储多个无序键值对,最大存储(2的32次方-1) 约40亿。

底层存储:zipList(双向链表:KV键值对小于512个 & KV长度小于64byte)

hashtable: (dictionary) hash冲突、rehash、扩容 (数组+ 链表)

跟String一样,String可以做的事,Hash基本都可以做。

结构:Map<Strig,Map<String,Object»

2021-11-23_redis结构之Hash

1.2.2 应用场景

购物车信息

2021-11-24_hash应用场景_我的订单

key:用户id, field:商品id, value:商品数量

+1:hincr

-1:hdecr

删除:hincrby key field -1

全选:hgetall

商品数:hlen
1.2.3 不适合场景
  • Field不能单独设置过期时间
  • 考虑数量分布问题(如果数据量多,无法分布到多节点)

1.3 List

1.3.1 存储类型

存储有序字符串,数据可重复,最大存储数据量约40亿。quicklist (有序双向链表) 数据+链表(与hash存储结构不一样的是内部编码)

ziplist 与 linkedlist

2021-11-23_redis结构之List

lpush/rpush
lpop/rpop
1.3.2 应用场景
1. 排序列表

: 用户消息列表、公告列表、活动列表、博客的文章列表等等。

思路:存储所有字段,LRANGE 取出一页内容,按顺序显示。

2. 消息队列

: 分布式消息队列(PUB/SUB)

1.4 Set

1.4.1 存储类型

存储String类型的无序集合,最大存储数量约40亿(2的32次方-1);用hashtable(数组+链表) 或intset 存储

2021-11-24_redis结构之SET

1.4.2 常用命令
# 添加元素(1个或多个)
sadd key a b c d 

# 获取所有元素
smembers key

# 统计元素
scard key

# 随机获取元素
srandmember key

# 随机弹出元素 (可用作抽奖)
spop key

# 移除元素
spop key a b 

# 查看元素是否存在
sismember key a

1.4.3 应用场景
  • 抽奖: spop key => 随机弹出

  • 点赞、签到、打卡: sadd key(like:消息id) userId1 userId2 userId3 ....

    2021-11-24_redis结构之SET_实例

  • 商品筛选:集合操作:交集

    2021-11-24_redis结构之SET_交集

    # 商品属性
    sadd brand:lenovo 联想小新Pro14
    sadd type:small 联想小新Pro14
    sadd cpu:intel 联想小新Pro14
    ...
      
    #商品筛选
    sinter brand:lenovo type:small cpu:intel    ==> 联想小新Pro14
    

    redis set 交集

  • 用户关注、推荐模型 (结构、交集)

1.5 ZSet
1.5.1 存储类型

sorted set 存储有序元素。每个元素都有个score,按照scocre 从小到大排列,socre相同,按照key 的ASCII码排序。

默认使用ziplist编码。

跳表:

2021-11-24_redis之ziplist-跳表

2021-11-24_redis结构之ZSET

1.5.2 常用命令
# 添加元素(注意顺序:分值在前)
zadd myzsetkey 10 a 20 b 30 c 40 d

# 获取全部元素
zrange myzsetkey 0 -1 withscores
zrevrange myzsetkey 0 -1 withscores

# 根据分值区间获取值
zrangebyscore myzsetkey 20 40

# 获取元素分值
zscore myzsetkey c

# 根据value 或 分值移除元素
zrem myzsetkey a b 
zrem myzsetkey 10

# 统计元素个数
zcard myzsetkey

# 根据分值区间或个数
zcount myzsetkey 10 30

# 分值递增(分值增加2)
zincrby myzsetkey 2 a

# 获取元素排名
zrank myzsetkey b

# 获取倒序
zrev myzsetkey
1.5.3 应用场景

会动态变化的顺序列表

  • 商品标签:

    2021-11-24_redis结构之SET_商品标签

  • 排行榜:(热榜、热搜)

    # 为新闻id为ID1000点击数增加1: zincrby hotnews:22222222 1 ID1000
    # 获取今天点击最多的10条数据:zrevrange hotnews:22222222 0 15 withscores
    

1.6 BitMaps

字符串类型上定义的位操作,1个字节有8个二进制表示。bit非常节省空间,可以用来做大数据量统计。在线用户统计

思路:如果用户id,对应一个ASCII码,即数字(且不重复)我们将设置具体的值,0101001.....  可以表示:从0-> 指定位数的最大值。如果某一个用户线下了,我们将对应bit位上的值设置0即可

=》类比:海量不重复数据中,查找数据是否存在。

1.7 HyperLogLog

不太精确的基数统计法,用来统计一个集合中不重复的元数个数,网页的UV;Redis中实现的HyperLogLog,只需要12K就能存储2的64次方个数据。

HyperLogLogTest分析

1.8 Geo

经纬度相关类型:计算距离等

redis-in-action

菜鸟教程

springboot-redis 使用

redis-in-action

redis 实战

ziplist 跳表

dockerlearn

REDIS缓存穿透,缓存击穿,缓存雪崩原因+解决方案


欢迎拍砖,多多交流,转载请注明出处:[没长正的技术专栏](http://blog.meizhangzheng.com) 如涉及侵权问题,请发送邮件到xsj34567@163.com,如情况属实本人将会尽快删除。


上一篇 Redis

下一篇 SQL高级用法

Comments

Content