【Redis】redis基本数据结构之ZSet
介绍:
ZSet数据结构类似于Set结构,只是ZSet结构中,每个元素都会有一个分值,然后所有元素按照分值的大小进行排列,相当于是一个进行了排序的链表。
如果ZSet是一个链表,而且内部元素是有序的,在进行元素插入和删除,以及查询的时候,就必须要遍历链表才行,时间复杂度就达到了O(n),这个在以单线程处理的Redis中是不能接受的。所以ZSet采用了一种跳跃表的实现。这个实现有点类似于Kafka存储消息是使用的稀疏索引,kafka这个相对较简单,可以用来介绍类比学习。
如果熟悉Kafka,就知道Kafka在进行持久化的时候,生成了两个文件,一个是xxxxxxx.log,一个是xxxxxxx.index,这其中log文件中以链表的形式保存着消息的详细信息,而index文件中,则是保存着这些消息的索引,或者说偏移量,但又不是每一条消息的索引都在index文件中存在,而是稀疏的,比如log文件中的消息的索引从0-10000,那么index文件中存储的索引可能是100, 500, 700, 1000, 5000, 6500,每一个索引中都保存着对应的log文件中的消息的具体位置,如图:
当要访问偏移量为899的这条消息时,先去index文件中查找,找到了700和1000这个区间,根据700这个索引中的信息,找到log文件中700这条消息的具体位置,然后顺序往下查找,直到找到索引为899的这条消息为止。从这个实现中我们可以看到,Kafka并没有进行log文件的整个遍历,而是通过index中的稀疏索引,找到消息在log中的大概位置,然后顺序遍历找到消息,这样就大大提高了查找的效率,如图:
Redis的跳跃表和上面类似,只是更加复杂一些,Kafka的稀疏索引只有一层,而Redis的索引被提取为多层。如图:
所有的元素都会在L0层的链表中,根据分数进行排序,同时会有一部分节点有机会被抽取到L1层中,作为一个稀疏索引,同样L1层中的索引也有一定机会被抽取到L2层中,组成一个更稀疏的索引列表。
下面用图来演示一下在对快速链表进行插入、删除、查询时,是如何定位到L0层中的具体位置的。
首先,假定有这么一个链表,注意这里只展示分数,而不展示具体的值了:
如果要查找分数为66的元素,首先在L2层的索引找。很明显,66位于25和85中间,这时就缩小了查找区间:
然后根据获得的区间,去L1对应的区间中查找,得到一个更精确的区间:
最终,根据这个更精确的区间,去L0层顺序遍历,即可得到要查找的元素:
上述即是对Redis的跳跃表的原理的一个简述。
这种跳跃表的实现,其实和二分查找的思路有点接近,只是一方面因为二分查找只能适用于数组,而无法适用于链表,所以为了让链表有二分查找类似的效率,就以空间换时间来达到目的。
跳跃表因为是一个根据分数权重进行排序的列表,可以再很多场景中进行应用,比如排行榜,搜索排序等等。
命令操作:
添加元素,zadd zsetName score1 value1 score2 value2 score3 value3 .....
查看所有元素,zrange zsetName 0 -1
查看所有元素,按score逆序排列, zrevrange zsetName 0 -1
元素数量,zcard zsetName
获取指定value的分数, zscore zsetName value
获取指定value的排名,zrank zsetName value(从0开始)
获取指定分值区间中的元素, zrangebyscore zsetName scoreStart scoreEnd(包含上下区间)(注意inf表示无穷大,-inf表示服务券大)
获取指定分值区间中的元素,并且返回分数, zrangebyscore zsetName scoreStart scoreEnd withscores
删除元素,zrem zsetName value
代码调用:
package mainimport ("fmt""github.com/garyburd/redigo/redis" )func main(){// 连接redisconn,err := redis.Dial("tcp", "localhost:6379")if err != nil {fmt.Errorf("connection redis failed. error info: ", err)return}// zadd_,err = conn.Do("zadd", "phones", "100", "Nokia", "80", "tianyu", "60", "xiaomifeng", "50", "shangshai")if err != nil {fmt.Errorf("sadd failed, error info: ", err)return}// zrangeresult,err := redis.Strings(conn.Do("zrange", "phones", "0", "-1"))if err != nil {fmt.Errorf("zrange failed, error info: ", err)return}fmt.Println(result)// zrevrangeresult,err = redis.Strings(conn.Do("zrevrange", "phones", "0", "-1"))if err != nil {fmt.Errorf("zrange failed, error info: ", err)return}fmt.Println(result)// zcardsize,err := conn.Do("zcard", "phones")if err != nil {fmt.Errorf("zrange failed, error info: ", err)return}fmt.Println(size)// zscorescore,err := redis.Int(conn.Do("zscore", "phones", "shangshai"))if err != nil {fmt.Errorf("zrange failed, error info: ", err)return}fmt.Println(score)// zrem_,err = conn.Do("zrem", "phones", "shangshai")if err != nil {fmt.Errorf("zrange failed, error info: ", err)return}fmt.Println("delete shangshai success.")// 关闭连接defer conn.Close() }
执行效果:
转载于:https://www.cnblogs.com/wuyizuokan/p/11108417.html
【Redis】redis基本数据结构之ZSet相关推荐
- Redis初学:9(Zset类型)
Zset(有序集合)类型 简介 Redis里面的有序集合Zset和集合Set非常相似,都是一个没有重复元素的字符串集合. 不同之处是有序集合Zset里面的每个成员都关联了一个评分(score),这个s ...
- Redis专题-底层数据结构与使用场景
Redis介绍 Redis是一种基于键值对的NoSQL数据库,是一个基于内存中的数据结构存储系统,可以用作数据库.缓存和消息中间件.它支持以string(字符串),hash(哈希),list(列表), ...
- redis创建像mysql表结构_如何给redis添加新数据结构
前言 作为一款缓存型nosql数据库,redis在诞生之初就以高性能.丰富的数据结构等特性获得业界的青睐.redis默认提供了五种数据类型的支持:string.list.set.zset.hash.针 ...
- Redis 之(二) Redis的基本数据结构以及一些常用的操作
本篇内容是Redis最简单最容易掌握的知识,如果你已经熟知了,就可以选择跳过啦! 要体验Redis,那么首先你得安装Redis,这边的话我就只讲一下Windows环境下的安装与操作: Window 下 ...
- 【学习笔记】Redis的geohash数据结构介绍
geohash介绍 ⾃Redis 3.2开始,Redis基于geohash和有序集合提供了地理位置相关功能.Redis Geo模块包含了以下6个命令: ▶GEOADD: 将给定的位置对象(纬度.经度. ...
- Redis五种数据结构
对redis来说,所有的key(键)都是字符串,所谓的5种数据结构是指针对value而言 1.Redis五种数据结构如下: 数据结构类型 说明 使用场景 常用方法 其他链接 String字符串类型 1 ...
- 头条面试题:请谈谈Redis 9种数据结构以及它们的内部编码实现
转载自 头条面试题:请谈谈Redis 9种数据结构以及它们的内部编码实现 90%的人知道Redis 5种最基本的数据结构: 只有不到10%的人知道8种基本数据结构,5种基本+bitmap+GeoHa ...
- 向内存中连续存入数据_内存节省到极致!Redis中这个数据结构,值得每个程序员了解...
在之前我们介绍了,Redis有五种基础数据类型,分别是String,Set,List,Hash与SortSet. 今天我们又学习了一个命令,我们可以使用DEBUG OBJECT key查询Redis中 ...
- redis源码分析 ppt_【Redis】redis各类型数据结构和底层实现源码分析
一.简介和应用 Redis是一个由ANSI C语言编写,性能优秀.支持网络.可持久化的K-K内存数据库,并提供多种语言的API.它常用的类型主要是 String.List.Hash.Set.ZSet ...
- redis专题:redis的常用数据结构及使用场景
文章目录 一. redis常用五大数据结构 〇:key的底层存储方式:SDS ①:string && 使用场景 ②:hash && 使用场景 ③:list && ...
最新文章
- OpenCV 中的 convertTo 函数
- 【数理知识】辛矩阵 symplectic
- Oracle 定义变量的方法
- mysql 集群备份脚本_mysqldump结合脚本的备份方案
- STL库中string类内存布局的探究
- .net 微服务实践
- php 数组转json乱码,php将数组转为json涌现中文乱码怎么办_后端开发
- MySQL Return JSON Value Attributes
- C#调用Matlab生成的dll方法
- 你有什么难忘的出差经历?
- Mac 上制作 SSL 证书
- ASP读取文件 ASP写入/保存文件
- 黑马程序员软件测试面试宝典
- 基于 Django 的图书馆借阅系统
- 在线考试系统,在线考试后台管理
- 如何给网站设置自定义图标(标签页显示,收藏夹显示)
- 门级仿真经验(SDF反标及其工作原理)
- uboot 下mmc read/write命令使用和验证方法
- matlab将空间描述转变为约当阵,matlab求约当标准型
- leafnotification_Notification Service
热门文章
- matlab练习程序(TV模型图像修复)
- Python机器学习库scikit-learn实践
- 7-200 天梯赛的善良 (20 分)
- 基于顺序存储结构的图书信息表的旧图书的出库(C++)
- 基于顺序存储结构的图书信息表的最爱图书的查找(C++)
- 求链表的倒数第m个元素
- java继承原理内存角度_Java编程的逻辑 (17) - 继承实现的基本原理
- linux中cat监控,Linux基本命令——cat、rev、head、tail
- linux内存锁定什么意思,Linux内存子系统——Locking Pages(内存锁定)
- 单向链表的简单Java实现-sunziren