Redis再探

前言

        前一篇文章我们深入分析了hash和list两种数据结构,并且列举了它们的使用场景,本篇文章我们将继续研究Redis支持的其他两种数据结构,set和zset。

1.1Set

        Set是一个无序集合,它不允许有重复元素。

  • 常用命令
Set常用命令
命令 描述
sadd key element 向set添加元素,返回结果为添加成功的元素个数。
srem key element 删除set中元素,返回结果为删除成功的元素个数。
scard key 计算set中元素的个数。
sismemeber key element 判断元素是否在集合中,如果在集合中则返回1,不存在返回0。
srandmemeber key [count] 随机从集合返回指定个数元素,count是可选参数,如果不写默认为1。
spop key 从集合中随机弹出元素。
s'members key 获取集合中所有元素,返回结果是无序的。
sinter key [key...] 求多个集合的交集。
suinon key [key...] 求多个集合的并集。
sdiff key [key...] 求多个集合的差集。
  • 内部数据结构

        Set在Redis中以intset或者hashtable来存储,对于Set,hashtable中的value永远为null。当set中只包含整数型的元素时并且元素个数小于set-max-intset-entries配置(默认512个)时,采用intset实现,否则使用hashtable。

        intset是一个字节数组,其中从小到大有序存放着set元素,我们先来看看intset数据结构

typedef struct intset {
    uint32_t encoding;
    uint32_t length;
    int8_t contents[];
} intset;

        其中encoding和length分别表示每个元素的编码方式和元素个数。redis根据整型位数将intset分为 INTSET_ENC_INT16INTSET_ENC_INT32INTSET_ENC_INT64 三种编码。

encoding 类型 字节
INTSET_ENC_INT16 int16_t 2
INTSET_ENC_INT32 int32_t 4
INTSET_ENC_INT64 int64_t 8

contents数组用来实际保存数据,数组中元素的特性:无重复元素;元素在数组中递增排列。

        进行插入操作时,首先通过二分查找找到本次插入的位置,再对元素进行扩容,再将预计插入位置之后的所有元素向后移动一个位置,最后插入元素。我们用一个流程图来详细描述插入流程,如下图所示

  • 使用场景

        我们知道服务发现一般有三个角色,服务提供服务消费者和服务中介。服务中介是联系服务提供者和服务消费者的桥梁。服务提供者将自己提供的服务地址注册到服务中介,服务消费者从服务中介那里查找自己想要的服务的地址,然后享受这个服务。服务中介就是一个字典,字典里有很多key/value键值对,key是服务名称,value是服务提供者的地址列表。服务注册就是调用字典的Put方法塞东西,服务查找就是调用字典的Get方法拿东西。当服务提供者节点挂掉时,要求服务能够及时取消注册,比便及时通知消费者重新获取服务地址。当服务提供者新加入时,要求服务中介能及时告知服务消费者,你要不要尝试一下新的服务。

        我们用一个set结构存储服务的IP:Port字符串。如果服务提供者加入,调用sadd命令加入服务地址,如果服务挂掉,调用srem命令移除服务地址。对服务消费者使用smembers指令获取所有服务地址然后在消费进程里随机挑一个,或者使用srandmemember指令直接获取随机服务地址。

        具体实现方式可以参考

http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247486144&idx=1&sn=b18374ad1bcb335b37935a209e30d340&chksm=e9c5f371deb27a6727b7d4836fbc403e00f5c9b4bbc00b502fcd36bf4d7f937aa55f4837da6f&scene=0#rd

1.2zset

        有序集合元素不能重复,并且集合中的元素可以排序。它为每个元素设置一个分数作为排序的依据。

  • 常用命令
zset常用命令
命令 描述
zadd key score member 添加成员,返回结果代表成功添加成员个数。
zcard key 计算成员个数。
zscore key member 计算某个成员的分数,如果成员不存在则返回nil。
zrank key member 按分数从低到高返回排名
zrevrank key member 按分数从高到低返回排名
zrem key member 删除成员
zincrby key increment member 增加成员的分数
zrange key start end  返回指定排名范围的成员
zrangebyscore key min max 返回指定分数范围的成员
  • 内部数据结构

        当有序集合的元素个数小于zset-max-ziplist-entries配置时(默认128个),同时每个元素值都小于zset-max-ziplist-value配置时(默认64字节),Redis会采用ziplist来作为有序集合的内部实现。当上述条件不满足时,会采用skiplist作为内部实现。

  • 使用场景

        有序集合比较典型的使用场景就是排行榜系统,例如视频网站需要对用户上传的视频做排行榜,比如按照获得的赞数进行排序。例如添加用户赞数可以使用:zadd user:ranking:2018_05_23 jack 3。如果此时在获得一个赞,可以使用:zincrby user:ranking:2018_05_23 jack 1。 如果想获得获取赞数最多的是个用户可以使用:zrevrangebyscore user:ranking:2018_05_23 0 9。

1.3总结

        今天我们分析了set和zset两种数据结构,下一篇文章我们主要讲一讲持久化的原理。

猜你喜欢

转载自my.oschina.net/u/3475585/blog/1817655