数据结构:

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. Vue使用antV G2制作看板

    工作中需要制作一个看板,选型选用antV G2进行开发. 由于项目前端是使用Vue,于是研究了antVG2在Vue中的使用. 1.安装antv/g2 npm install @antv/g2 --sa ...

  2. Win7安装解压版MySQL

    1.下载MySQL 访问https://dev.mysql.com/downloads/mysql/5.6.html#downloads,下载操作系统对应的版本(无账号需先注册一个),以mysql-5 ...

  3. BigInt 的使用!

    今天学长讲的卡特兰数真的是卡的一批,整个全是高精的题,这时我就使用重载运算符,然后一下午就过去了 首先来看一波水题(也就卡了2小时) . A. 网格 内存限制:512 MiB 时间限制:1000 ms ...

  4. jquery mobiscroll移动端日期选择控件(无乱码)

    jquery mobiscroll移动端日期选择控件(无乱码) <pre><!DOCTYPE html><html lang="en">< ...

  5. 013.Kubernetes二进制部署worker节点Nginx实现高可用

    一 Nginx代理实现kube-apiserver高可用 1.1 Nginx实现高可用 基于 nginx 代理的 kube-apiserver 高可用方案. 控制节点的 kube-controller ...

  6. java编程思想第四版第十三章字符串 习题

    fas 第二题 package net.mindview.strings; import java.util.ArrayList; import java.util.List; /** * 无限循环 ...

  7. rabittmq详解

    交换机(exchange): 声明交换机: Name Durability (消息代理重启后,交换机是否还存在) Auto-delete (当所有与之绑定的消息队列都完成了对此交换机的使用后,删掉它) ...

  8. mysql中int、bigint、smallint、tinyint 长度

    mysql中int.bigint.smallint.tinyint 长度 bigint -2^63 (-9223372036854775808) 到 2^63-1 (92233720368547758 ...

  9. 0xe7f001f0!?NDK调试过程,无故抛出SIGSEGV。

    arm调试过程,如果抛一个SIGSEGV,地址在 0xe7f001f0 附近,原因居然是因为我在调试.当我使用n指令跳到下一行代码时,往往变成了continue指令一样地执行.还不确定地抛出SIGSE ...

  10. react-hook生命周期

    ① useEffect相当于componentDidMount和componentDidUpdate两个生命周期函数 ②useEffect是异步的 ========================== ...