Redis: Sorted Set 底层算法的简单分析

概述

  • 我们先看下 Shorted Set 有序集合的内部数据结构
  • 所谓有序集合,比如有个容器,容器里边都已经排好序了,那无非就是快速的查找和插入
  • 不管你是查找还是插入,肯定要确定那个位置
  • 最简单的办法就是从最开头开始,挨个比较最终找到我们的位置
  • 这个实际上在数据集比较大的时候,它的性能就会比较低了
  • 它的时间复杂度是O(n),实际上可以提升至 O(logn)

算法选择和分析


1 ) 二分查找

  • 在一个单调有序的集合中查找元素
  • 步骤
    • 每次将集合分为左右两部分
    • 判断解在哪个部分中并调整集合上下界
    • 重复直到找到目标元素
  • 时间复杂度 O(logn) 优于直接顺序查找 O(n)
  • 在 Sorted Set 里边不是用二分查找来快速的实现插入和读取的
  • 二分查找的限制是:有序的数组,而 Sorted Set 用的是链表
  • 这里用了一种新的数据结构,叫做跳跃列表 SkipList

2 )跳跃列表 SkipList

  • 它算法的核心思想是用空间换时间

  • 跳表由多条链表 L0 … LN 以及下行指针构成

  • 最底下的是原始链表,把原始链表里边的这每一个节点,随机做节点升级

  • 第一级索引链表是新构建出来的链表,是原始链表的子集,可理解为其索引

  • 要实现快速查找,基于此种方式,可进行再次升级,如上图所示

  • 这里有4层,L0 ~ L3 这 4 层链表

  • 在原始链表中,比如黄色部分是有序的,它是由score来排序的,浅蓝色为value值

  • 这个节点升级是内部有一个随机的算法,这个随机算法是概率性的

  • 这个算法作者根据概率性,做节点随机升级,就像抛硬币一样

  • 这个算法经过了大量的测试之后,有极少部分情况下会出现O(n)的情况

  • 它不影响整体时间复杂度为 O(logn), 这种属于正常现象

  • 在这个跳跃列表里边,如何去找的呢?

    • 它是从最顶层开始找的,然后找不到回来就往下走,最终到原始链表
    • 在这个过程中找到立即停止,如果没有找到,则查找失败
  • 再来看下链表的构建过程

    • 每一个链表,包括我们的原始链表和上层构建出来
    • 在这些索引列表中,每一个都是从负无穷到正正无穷大
    • 这里面score从负无穷大始一直到正无穷大,然后它内部做了一个排序
  • 现在要去快速的查找和插入它

    • 内部它自己会根据概率算法先升级构建链表
    • 升级之后,现在要去处理,要去找的话,就是从最顶层开始
    • 如上图,逐层跳跃查找
    • 最后用完了链表都找不到,则查找失败
    • 这是完整的查找过程
  • 它实际上是一个zip list,就是压缩的列表

  • 那为什么不用红黑树平衡树来实现,为什么要用跳入列表?

    • 首先,跳跃列表,红黑树,平衡树,它们最终的时间复杂度都是o(logn),就是它们的性能都是一样的
    • 从源码上去出发的话,跳跃列表的实现是完全要简单于红黑树和平衡树的
    • Redis 作者在构建建这个 sorted set 的时候,会有几点考虑
    • 如果用红黑树平衡树,写这个源码的过程中可能会比较复杂
    • 考虑到它要开源,后续可能很多人要过来看源码学习
    • 相对于简单的跳跃列表 skip list 来现整个过程,它的性能有没有降低

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/880826.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【unity进阶知识6】Resources的使用,如何封装一个Resources资源管理器

文章目录 一、Unity资源加载的几种方式1、Inspector窗口拖拽2、Resources3、AssetBundle4、Addressables(可寻址资源系统)5、AssetDatabase 二、准备三、同步加载Resources资源1、Resources.Load同步加载单个资源1.1、基本加载1.2、加载指定类型的资源1.…

C++ 语言特性07 - 静态成员的初始化

一:概述 1. 静态成员变量通常在类定义内部声明,并在类定义外部定义和初始化。 class MyClass { public:static int staticVar; // 声明 };int MyClass::staticVar 42; // 定义和初始化 2. 从C11开始,可以在类内直接初始化静态数据成员&am…

无源码实现免登录功能

因项目要求需要对一个没有源代码的老旧系统实现免登录功能,系统采用前后端分离的方式部署,登录时前端调用后台的认证接口,认证接口返回token信息,然后将token以json的方式存储到cookie中,格式如下: 这里有…

H.264编解码工具 - x264

一、简介 x264是一个开源的H.264/AVC视频编码库,它可以将视频数据压缩成H.264格式,并且可以从H.264格式解码出原始视频数据。 x264是以C语言编写的,并且可以在多个平台上使用,包括Windows、Linux和Mac OS等操作系统。 x264具有很高的编码效率和视频质量,它支持多种编码…

HTTPS加密流程

本文尽量用最小的篇幅来介绍HTTPS的加密过程,如果还看不懂可以参考文末尾的文章。 加密算法 先简单介绍一下HTTPS中使用的是混合加密算法,即对称加密和非对称加密的混合使用: 1.对称加密:顾名思义就是加密和解密都是使用同一个密钥。 优点…

MySQL 问题小结

mysqld --initialize 初始化 data 文件夹 初始化的密码在这个 err 文件夹中

DC00025【含论文】基于协同过滤推荐算法springboot视频推荐管理系统

1、项目功能演示 DC00025【含文档】基于springboot短视频推荐管理系统协同过滤算法视频推荐系统javaweb开发程序设计vue 2、项目功能描述 短视频推荐系统分为用户和系统管理员两个角色 2.1 用户角色 1、用户登录、用户注册 2、视频中心:信息查看、视频收藏、点赞、…

Pyenv管理Python版本,conda之外的另一套python版本管理解决方案

简介 Pyenv 是一个 python 解释器管理工具,可以对计算机中的多个 python 版本进行管理和切换。为什么要用 pyenv 管理python呢,用过的 python 人都知道,python 虽然是易用而强大的编程语言,但是 python 解释器却有多个版本&#…

数据链路层 ——MAC

目录 MAC帧协议 mac地址 以太网帧格式 ARP协议 ARP报文格式​编辑 RARP 其他的网络服务或者协议 DNS ICMP协议 ping traceroute NAT技术 代理服务器 网络层负责规划转发路线,而链路层负责在网络节点之间的转发,也就是"一跳"的具体传输…

Qt_绘图

目录 1、绘图核心类 2、QPainter类的使用 2.1 绘制线段 2.2 绘制矩形 2.3 绘制圆形 2.4 绘制文本 3、QPen类的使用 3.1 使用画笔 4、QBrush类的使用 4.1 使用画刷 5、绘制图片 5.1 测试QPixmap 5.1.1 图片移动 5.1.2 图标缩小 5.1.3 旋转图片 5.1.4 将…

esp32 命令行 编译 下载 调试

选择芯片型号 idf.py set-target esp32s3 编译程序 idf.py build 下载程序 idf.py -p PORT [-b BAUD] flash 串口监听 idf.py -p PORT monitor 退出监听 Ctrl] 使用VScode打开文件夹 code . 快速入门 - ESP32 - — ESP-IDF 编程指南 v4.4.3 文档 https://docs.espressif.com/pr…

【四】Spring Cloud OpenFeign原理分析

Spring Cloud OpenFeign原理分析 概述 Spring Cloud 微服务实践也有挺多年了,一直想着总结一下这系列的知识点,最近终于下定决心来出一个Spring Cloud 系列文章了。本文主要围绕fegin组件来进行讲解,文中将会给出基础使用的示例,还…

java将mysql表结构写入到word表格中

文章目录 需要的依赖 需要的依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.9</version> </dependency> <!--07版本的&#xff0c;行数不受限制--> <dependency>&l…

Python中的属性装饰器:解锁数据封装的新境界

引言 随着软件复杂度的不断增加&#xff0c;如何有效地管理类内部的数据变得愈发重要。属性装饰器作为一种强大的工具&#xff0c;不仅简化了代码&#xff0c;还增强了程序的可读性和可维护性。通过使用属性装饰器&#xff0c;我们可以轻松地实现对类属性的读取、修改以及删除…

docker-compose 快速部署clickhouse集群

在本教程中&#xff0c;我们将学习如何使用 Docker Compose 部署一个带有三节点的 ClickHouse 集群&#xff0c;并使用 ZooKeeper 作为分布式协调服务。 前提条件 注意事项&#xff1a; 镜像版本号注意保持一致 [zookeeper:3.7, clickhouse/clickhouse-server:22.5.4]config…

gcc选项-fno-access-control 使用

背景&#xff1a; 在进行eigen库进行移植时&#xff0c;总是报编译错误&#xff1a; error: struct std::basic_stringbuf<_CharT, _Traits, _Alloc>::__xfer_bufptrs redeclared with different access struct __xfer_bufptrs &#xff0c;单独写一个测试程序使用eig…

uniapp微信小程序使用ucharts遮挡自定义tabbar的最佳解决方案

如图所示&#xff1a; 使用的ucharts遮挡住了我自定义的tabbar&#xff08;如果不是提需求的有病&#xff0c;我才不会去自定义tabbar&#xff09; 查阅了不少文档&#xff0c;说是开启 ucharts 的 canvas2d 即可&#xff1a; 官网文档地址&#xff1a; uCharts官网 - 秋云…

Android Debug Bridge(ADB)完全指南

文章目录 前言一、什么是ADB&#xff1f;二、ADB的工作原理ADB由三个部分组成&#xff1a; 三、如何安装ADBWindows系统&#xff1a;macOS和Linux系统&#xff1a; 四、ADB常用指令大全设备相关操作1. 查看连接的设备&#xff1a;2. 重启设备&#xff1a;3. 进入Bootloader模式…

资源《Arduino 扩展板1-LED灯》说明。

资源链接&#xff1a;Arduino 扩展板1-LED灯 1.文件明细&#xff1a; 2.文件内容说明 包含&#xff1a;AD工程、原理图、PCB。 3.内容展示 4.简述 该文件为PCB工程&#xff0c;采用AD做的。 该文件打板后配合Arduino使用&#xff0c;属于Arduino的扩展板。 该文件主要有…

docker 私有仓库的镜像删除

目录 获取token1. base64 用户名 密码2. 先请求要请求的接口3. 请求接口 auth4. 拿着 token, 去请求接口 请求 tag 列表接口1. 去请求token2. 拿着token去请求 镜像 tag 列表 删除镜像1. 先获取镜像 tag 的 sha2562. 删除镜像 错误: {"errors":[{"code":&q…