Redis ZSet底层实现以及ZSet实现延时队列

2020-05-08  本文已影响0人  HannahLi_9f1c

将知识从定义、来源、实现、问题、优化、应用方面来系统性的回答

Zset原理

有序集合对象是有序的。与列表使用索引下标作为排序依据不同,有序集合为每个元素设置一个分数(score)作为排序依据

ZSet底层如何实现

一、使用ziplist。
  1. 前提:保存元素数量小于128,并且每个元素长度小于64字节
    (这两个参数可以通过zset-max-ziplist-entries 选项和 zset-max-ziplist-value 进行修改)
  2. ziplist原理:
    压缩列表(ziplist)是Redis为了节省内存而开发的,是由一系列特殊编码的连续内存块组成的顺序型数据结构,一个压缩列表可以包含任意多个节点(entry),每个节点可以保存一个字节数组或者一个整数值。
    image
image
二、使用字典和跳跃表
typedef struct zset{
     //跳跃表
     zskiplist *zsl;
     //字典
     dict *dice;
} zset;

字典的键保存元素的值,字典的值则保存元素的分值;跳跃表节点的 object 属性保存元素的值,跳跃表节点的 score 属性保存元素的分值。

为什么不直接用跳跃表

假如我们单独使用 字典,虽然能以 O(1) 的时间复杂度查找成员的分值,但是因为字典是以无序的方式来保存集合元素,所以每次进行范围操作的时候都要进行排序;假如我们单独使用跳跃表来实现,虽然能执行范围操作,但是查找操作有 O(1)的复杂度变为了O(logN)。因此Redis使用了两种数据结构来共同实现有序集合。

字典

字典中的键是唯一的,可以通过key来查找值

跳跃表

跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其它节点的指针,从而达到快速访问节点的目的。


image
  1. 性质
  1. 定义
typedef struct zskiplistNode {
     //层
     struct zskiplistLevel{
           //前进指针
           struct zskiplistNode *forward;
           //跨度
           unsigned int span;
     }level[];
 
     //后退指针
     struct zskiplistNode *backward;
     //分值
     double score;
     //成员对象
     robj *obj;
 
} zskiplistNode
typedef struct zskiplist{
     //表头节点和表尾节点
     structz skiplistNode *header, *tail;
     //表中节点的数量
     unsigned long length;
     //表中层数最大的节点的层数
     int level;
 
}zskiplist;
  1. 操作

  1. ZSet延时队列如何实现
    Java延时队列

本文参考:

https://www.cnblogs.com/ysocean/p/9080942.html#_label3

上一篇 下一篇

猜你喜欢

热点阅读