数据结构:

zset是有序的,不运行重复的,带有分值score的

数据结构对比:

操作命令:

zadd myzset 10 java 20 python 20 ruby 40 mysql 50 php (添加)

zrange myzset 0 -1 withscores (通过score进行排序从小到大)

zrevrange myzset 0 -1 withscores (通过score进行排序从大到小)

zrangebyscore myzset 20 30 (通过score取出20-30的产品)

zrem myzset java python (将java和python移除)

zscard myzset (统计总数)

zincrby myzset 5 java (将java加5分)

zcount myzset 20 50 (统计20-50之间有多少个)

zrank myzset java (java在set中处于第几个位置,从0开始)

zscore myzset java (java有多少分)

存储实现原理:

在redis.conf文件中有两行这么写的

zset-max-ziplist-entries 128  # zset中压缩列表ziplist最大的元素是128个,超过128将会使用跳表skiplist+dict来存储

zset-max-ziplist-value 64 # zset中压缩列表ziplist中每个元素最大的个数是64个,超过64将会使用跳表skiplist+dict来存储

什么是跳表skiplist dict呢?我们先来看下面一张图:

这是一个有序的链表,当我们要将20这个数字插入到链表中的时候,他是从开始到结尾一个一个进行比对直到找到21之后才停止,这样他的效率就很低,时间复杂度是O(n),查找也是一样的道理。

怎么优化呢,skiplist是怎么实现的呢?再来看下面一张图:

假如我们每相邻两个节点增加一个指针(或者理解为有三个元素进入了第二层),让指针指向下下个节点。

这样所有新增加的指针连成了一个新的链表,但它包含的节点个数只有原来的一半(上图中是 7, 19, 26)。在插入一个数据的时候,
决定要放到那一层,取决于一个算法(在 redis 中 t_zset.c 有一个 zslRandomLevel 这个方法)。现在当我们想查找数据的时候,可以先沿着这个新链表进行查找。当碰到比待查数
据大的节点时,再回到原来的链表中的下一层进行查找。比如,我们想查找 23,查找的路径是沿着下图中标红的指针所指向的方向进行的:

1. 23 首先和 7 比较,再和 19 比较,比它们都大,继续向后比较。
2. 但 23 和 26 比较的时候,比 26 要小,因此回到下面的链表(原链表),与 22比较。
3. 23 比 22 要大,沿下面的指针继续向后和 26 比较。23 比 26 小,说明待查数据 23 在原链表中不存在,在这个查找过程中,由于新增加的指针,我们不再需要与链表中每个节点逐个进行比较了。需要比较的节点数大概只有原来的一半。这就是跳跃表。

可以看到他将某些元素中加了指针,这有点类似于数组中的二分法查找,但是链表中没有数组,所以用指针的方式来实现,看下面源码

源码位置:server.h
typedef struct zskiplistNode {
sds ele; /* zset 的元素 */
double score; /* 分值 */
struct zskiplistNode *backward; /* 后退指针 */
struct zskiplistLevel {
struct zskiplistNode *forward; /* 前进指针,对应 level 的下一个节点 */
unsigned long span; /* 从当前节点到下一个节点的跨度(跨越的节点数) */
}level[]; /* 层 */
}zskiplistNode; typedef struct zskiplist {
struct zskiplistNode *header, *tail; /* 指向跳跃表的头结点和尾节点 */
unsigned long length; /* 跳跃表的节点数 */ int level; /* 最大的层数 */
} zskiplist; typedef struct zset {
dict *dict;
zskiplist *zsl;
} zset;

随机获取层数的函数,源码位置t_zset.c

int zslRandomLevel(void) {
int level = 1;
while ((random()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF))
level += 1;
return (level<ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL;
}

应用场景:

排行榜

id 为 6001 的新闻点击数加 1:zincrby hotNews:20190926 1 n6001
获取今天点击最多的 15 条:zrevrange hotNews:20190926 0 15 withscores

redis数据类型--zset的更多相关文章

  1. 初识redis数据类型

    初识redis数据类型 1.String(字符串) string是redis最基本的类型,一个key对应一个value. string类型是二进制安全的.意思是redis的string可以包含任何数据 ...

  2. Redis数据类型介绍

    Redis 数据类型 Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). String(字符串) st ...

  3. redis数据类型

    Redis 数据类型 Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). String(字符串) st ...

  4. redis笔记总结之redis数据类型及常用命令

    三.常用命令 3.1 字符串类型(string) 字符串类型是Redis中最基本的数据类型,一个字符串类型的键允许存储的数据的最大容量为512MB. 3.1.1 赋值与取值: SET key valu ...

  5. redis底层设计(三)——redis数据类型

    今天我们来看一下redis的数据类型.既然redis的键值对可以保存不同类型的值,那么很自然就需要对键值对的类型进行检查以及多态处理.下面我们将对redis所使用的对象系统进行了解,并分别观察字符串. ...

  6. Redis笔记(二):Redis数据类型

    Redis 数据类型 Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). String(字符串) st ...

  7. Redis 基础:Redis 数据类型

    Redis 数据类型 Redis支持五种数据类型:string(字符串).hash(哈希).list(列表).set(集合)及zset(sorted set:有序集合). String(字符串) st ...

  8. Redis数据类型及常用命名总结

    Redis数据类型: Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合).  1.String(字符串) ...

  9. Redis(三):Redis数据类型

    Redis数据类型目录导航: Redis五大数据类型 哪里去获取Redis常见数据类型操作命令 Redis键(Key) Redis字符串(String) Redis列表(List) Redis集合(S ...

随机推荐

  1. Jmeter与压测相关概念

    相关概念 RT(response time) 什么是RT? RT就是指系统在接收到请求和做出相应这段时间跨度 但是值得一提的是RT的值越高,并不真的就能说明我们的系统的吞吐量就很高, 比如说,如果存在 ...

  2. layer弹框的上面各个属性 -可配置

    <script type="text/javascript"> 12 //eg 13 layer.open({ 14 title:"标题信息提示", ...

  3. Conda/Miniconda/Anaconda 常用命令整理及介绍

    作者:HELO 出处:http://www.cnblogs.com/HELO-K 欢迎转载, 转载时请保留此声明, 谢谢! 在这里整理一份全一点的 Conda 常用命令, 方便大家日常使用时参考, 一 ...

  4. T-SQL, Part III: Check table's existance

    There are several approaches to achieve so. Just list out all approaches I have tried: Approach 1: s ...

  5. opencv 6 图像轮廓与图像分割修复 1 查找并绘制轮廓 寻找物体的凸包

    查找并绘制轮廓 寻找轮廓(findContours)函数 绘制轮廓(drawContours()函数) 基础实例程序:轮廓查找 #include <opencv2/opencv.hpp> ...

  6. 剑指Offer-23.二叉搜索树的后序遍历序列(C++/Java)

    题目: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. 分析: 二叉树的后序遍历也就是先访问左子树,再访问右 ...

  7. kafka connector 使用总结以及自定义connector开发

    Kafaka connect 是一种用于在Kafka和其他系统之间可扩展的.可靠的流式传输数据的工具.它使得能够快速定义将大量数据集合移入和移出Kafka的连接器变得简单.Kafka Connect可 ...

  8. python_08

    一.作业 ''' 主页: 图标地址.下载次数.大小.详情页地址 详情页: 游戏名.好评率.评论数.小编点评.下载地址.简介.网友评论.1-5张截图链接地址. https://www.wandoujia ...

  9. location 优先级

    ###我只是个搬运工 规则 等号类型(=)的优先级最高.一旦匹配成功,则不再查找其他匹配项 前缀普通匹配(^~)优先级次之.不支持正则表达式.使用前缀匹配,如果有多个location匹配的话,则使用表 ...

  10. (三十八)golang--json(对切片、map、结构体进行序列化)

    JSON(javascript object notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成.key-val JSON是在2001年开始推广的数据格式,目前已 ...