首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis的数据结构和应用场景

Redis的数据结构和应用场景

作者头像
春哥大魔王
发布2020-06-28 18:07:22
8400
发布2020-06-28 18:07:22
举报

基本数据结构

redis的五种数据结构:

  1. String 字符串
  2. List 列表
  3. Set 无序集合
  4. ZSet 有序集合
  5. Hash 哈希类型

以上所有的结构都可以采用redisObject来表示,redisObject中,type表示的是属于哪种数据类型,encoding表示底层实现的该数据类型的数据结构。

String

String 一般用于存储 key-value的情况,也是比较常用的数据结构。

比如文章阅读数,点赞数,粉丝数量统计等。

Hash

Hash 底层有ziplist,hashtable。

ziplist 压缩列表,是一组连续内存块组成的顺序数据结构,压缩列表可以节省空间,压缩列表中使用多个节点存储数据。

他并不是以某种压缩算法进行压缩数据,而是一组连续的内存空间,这样可以节省空间。

hashtable key是string类型,value是key-value形式存储。

hashtable和hashmap原理类似,新增key时先计算key的数组下标,hashmap是以hash函数方式计算,hashtable是通过sizemask属性和哈希值再次计算得到下标。

hash表可能存在hash冲突,比如不同的key通过计算得到同一个index,就会形成单向链表。

从上图可以看出来,value对象是以每一个dicEntry的对象进行存储,当hash中key值不断增加或者减少时,需要对hash表进行扩展或者收缩,比如ht[0]和ht[1],在rehash过程中可能会将ht[0]的键值对重新散列到ht[1]中。

由于hash有这种key - (key - value)的特点,可以用来存储用户数据,以前可能习惯于将用户实体对象进行序列化,整体存储到redis中,比如:

这种多了序列化和使用时反序列化的过程和成本开销。如果只需要修改其中一个值,比如电话,整个对象都需要拿出来做修改,造成不必要的开销。

用hash存储就是个比较好的选择,同时能减少序列化产生的开销,比如userid-(name-xxx,age-xxx)。

List

list底层使用了linkedlist和quicklist。

linkedlist和quicklist底层都是一个双向链表,有指向后节点的指针,插入,修改,更新时间复杂度都是O(1),但查询时间复杂度为O(n)。

redis链表的特点:

  1. 每个节点都有指向前一个节点和后一个节点的指针。
  2. 头节点和尾节点的prev和next指针指向为null,所以链表是无环的。
  3. 链表有自己长度信息,获取长度时间复杂度为O(1)。

列表一般用于实现一个队列,通过lpush和brpop可以实现操作。生产者使用lpush从队列左侧插入数据,消费者使用brpop从队列右侧获取数据进行消费。

所以类似于队列这种场景可以考虑采用list。

Set

Set可以用来存储字符串,Set是不可重复的,List是可以存储相同的。Set是无序的,ZSet是有序的。

Set底层是hash和inset。

hash同前文。

inset是整数集合,用于保存整数值的数据结构类型,可以保存16位,32位,64位。

如果整数集合长度超出了原集合长度大小,会对集合进行升级:

  1. 扩展底层数组大小
  2. 将原有数组中数据放到扩展后数据响应位置

Set集合这种可以用来处理去重数据的场景,比如好友列表。

ZSet

ZSet是有序的,Set是无序的 不可重复的,List是可以重复的。

ZSet底层是ziplist和skiplist。

skipList是跳跃表,是一种有序的数据结构,通过一个节点维持多个指向其他节点的指针,实现了快速访问。

跳跃表上层相当于索引,都是为了找到最后的数据而服务的,数据量越大,跳表体现的效率也就越好,和平衡树查询效率相差无几。

因为ZSet是有序的,所以在排序场景业务上比较常见,比如首页推荐的top10的热搜,阅读量由高到低的帖子,歌手排行榜之类的。

总的来说

总的来说List是无序的,Set是有序的,不重复的,一般关注的人,或者粉丝列表可以分别放到不同的Set内。并且针对于Set,redis提供了对集合求交集,并集,差集等操作,就可以很好的对不同集合进行处理了。

比如做一个投票排行榜,要去每次投票增1,需要更新最后的投票实现,实现排序。

比如score是数字类型的,同分情况下按照先来的顺序排序,可以对score部分进行改造,score分成两部分,一部分分值,一部分时间,时间戳越来越大,考虑到时间戳可能越来越大,可以采用一个时间差的方式,比如以距离活动结束时间时间差来计算,这样长度合适,还可以满足先来后到的原则。

  1. redis 127.0.0.1:6379> ZADD w3ckey 1 redis
  2. (integer)1
  3. redis 127.0.0.1:6379> ZADD w3ckey 2 mongodb
  4. (integer)1
  5. redis 127.0.0.1:6379> ZADD w3ckey 3 mysql
  6. (integer)1
  7. redis 127.0.0.1:6379> ZADD w3ckey 3 mysql
  8. (integer)0
  9. redis 127.0.0.1:6379> ZADD w3ckey 4 mysql
  10. (integer)0
  11. redis 127.0.0.1:6379> ZRANGE w3ckey 010 WITHSCORES
  12. 1)"redis"
  13. 2)"1"
  14. 3)"mongodb"
  15. 4)"2"
  16. 5)"mysql"
  17. 6)"4"
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 春哥talk 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档