高级数据结构
)哈希(hash)
- 数据结构
Redis的hash对象,采用了两种方式来实现的。前面分析过连续内存和非连续内存各自的优缺点,在这里hash表也折中了这两种情况。
| |
注意点
- 由ziplist转dict的操作是不可逆的。
- 尽可能的使用ziplist来作为hash底层实现。长度尽量控制在1000以内,否则由于存取操作时间复杂度在O(n)到O(n^2)之间,长列表会导致CPU消耗严重。使用1KB以上的对象,hash-ziplist结构控制键数量反而得不偿失。
- 两个参数【hash-max-ziplist-entries和hash-max-ziplist-value】可在配置文件中进行修改
- ziplist作为底层对象时,其查找的时间复杂度为O(n)
使用场景
存储对象(定长或者不定长属性)
原生字符串
123set user:1:name tomset user:1:age 23set user:1:city beijing- 优点:简单直观,每个属性都支持单独更新
- 缺点:占用过多的键,内存占用量大,同时用户信息内聚性差,生产环境比较少用
序列化字符串
1set user:1 serialize(userInfo)- 优点:简化编程,如果合理利用序列化,可以提高内存的使用率
- 缺点:序列化和反序列化有一定的开销,同时每次更新属性都需要把全部数据都提取出来进行反序列化,更新后在重新序列化
哈希类型
1hmset user:1 name tom age 23 city beijing- 优点:简化编程,如果合理利用序列化,可以提高内存的使用率。每个用户属性使用一对field-value,但只用一个键保存。
- 缺点:要控制哈希在ziplist和hashtable两种内部编码的转换,hashtable会消耗更多内存。
)集合(set)
- 数据结构
Redis的set对象,也是采用了两种方式来实现的。
| |
注意点
- 由intset转dict的操作是不可逆的。
- set是不允许重复的。
- 支持交并补
- 参数【set-max-intset-entries】可在配置文件中进行修改
- dict作为底层对象时,value值为null
- intset作为底层对象时,其查找的时间复杂度为O(logN)
使用场景
标签:主要是用于社交里面感兴趣的内容(注意尽量保证一个事务下完成)
用户添加标签
1234sadd user:1:tags tag1 tag2 tag5sadd user:2:tags tag2 tag3 tag5...sadd user:k:tags tag1 tag2 tag4给标签标记用户
12345sadd tag1:users user:1 user:3sadd tag2:users user:1 user:2 user:3...sadd tagk:users user:1 user:2...计算用户共同感兴趣的标签
1sinter user:1:tags user:2:tags
抽奖中随机数
1spop/srandmember
)有序集合(zset)
数据结构
1234typedef struct zset { dict *dict;//字段 zskiplist *zsl;//线段跳表} zset;
注意点
- 在skiplist的基础上,还需要创建dict的原因是当需要获取某个元素的score时,skplist的时间复杂度为O(n),而dict时间复杂度为O(1).(见zsetAdd)
- skiplist和dict共享元素和分值(指针复制)。
- 由ziplist转skiplist的操作是不可逆的。
- 两个参数【zset-max-ziplist-entries和zset-max-ziplist-value 】可在配置文件中进行修改。
- zset也不允许重复。
使用场景
优先队列
排行榜系统:主要是视频网站需要对用户上传的视频做排行榜,榜单的维度可能是多个方面的:按照时间、按照播放数量、按照获得的赞数。
添加用户赞数
1zadd user:ranking:2016_03_15 3 mike有人点赞
1zincrby user:ranking:2016_03_15 1 mike取消点赞
1zrem user:ranking:2016_03_15 mike展示获取赞数最多的十个用户
1zrevrange user:ranking:2016_03_15 0 9展示用户信息以及用户分数和排名
123hgetall user:info:tomzscore user:ranking:2016_03_15 mikezrank user:ranking:2016_03_15 mike
小小总结
| 数据类型 | 适用场景 | 备注 |
|---|---|---|
| 字符串(string) | 缓存;计算器 | 简单型的。如set stunum studentInfo。计数器如限流 |
| 列表(list) | lpush+lpop=Stack(栈) lpush+rpop=Queue(队列) lpush+ltrim=Capped Collection(有限集合) lpush+brpop=Message Queue(消息队列) | 如阻塞队列,关注列表 |
| 哈希(hash) | 对象属性(尤其不定长的) | 如缓存studentInfo,hmset stunum stunum 1 stuname dinghaha age 18 |
| 集合(set) | 适用社交场景 | 赞/踩、粉丝、共同好友/喜好、推送 |
| 有序集合(set) | 排行榜;优先队列;缓存相关的元数据(比如按照排序的挑战) |