`
on__the__way
  • 浏览: 24030 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

redis的几种数据结构

 
阅读更多

 通过分析底层的数据结构,学习如何根据场景选型和设计

 1,简单动态字符串

    redis使用的字符串SDS有别于C语言中的字符串

   a, 结构

 

    free字段为已分配但未使用的空间

    len为已使用的空间(不计入'\0')

    buf为char数组

    b, 与C字符串区别

        redis的字符环结构可以理解为将C字符串封装了一层,通过加入的属性字段降低字符串操作的复杂度,提高安全性。

        通过len属性可以在常数复杂度获取字符串的长度,仅通过len属性可直接获取长度,而C语言字符串复杂度需要遍历,长度为O(N)。

        二进制安全的。C字符串是ASCII编码的,以'\0'来判断字符串是否结束,如果数据中包含'\0'字符便会将数据截断,当做两个字符串,因此仅限于保存文本数据。redis字符串通过len属性来获取数据而不是通过遍历寻找结束标志,因此可以存储任意内容的二进制数据。

        兼容C字符串的操作。默认在字符串最后加'\0‘,使用C库字符串的部分操作。

        避免缓冲区溢出。其实原理就是根据redis字符串的特点重写了C可能造成内存溢出的函数,如strcat拼接字符串函数,C语言中需人为保证目标字符串的空间足够大,否会造成溢出,而redis字符串通过free属性来自动判断是否可容纳源字符串,否则会扩展自身内存再拼接。

        减少内存分配次数。空间和效率的问题,redis采用的是牺牲空间来换取效率的提升,避免多次的申请或释放内存。redis是kv型数据库,要求速度快,数据也多为频繁修改,因此牺牲一部分空间是可取的。它提供了两种策略,空间预分配和惰性释放。预分配指的是一个字符串修改后会同时分配一定大小的空间给free预留,避免再次修改分配内存。惰性释放是字符串缩短后不是放空间而是给free记录,避免释放空间。

    预分配和惰性释放在memcache中也使用了,不过它是从内存管理的角度出发的。通过在初始化时对整个内存进行预分配,减少动态申请内存的操作带来的消耗,使用的内存都是连续的,避免了内存碎片,内存也不会回收而是通过内个slab的slot指针数组来保存。关于memcache的内存管理的机制具体见这里

    c, 场景

        该类型是字符串对象的一种实现方式,并用于AOF缓冲区和客户端输入缓冲区。

 

2,链表

    redis使用的联表示标准的双端无环链表

    a, 结构

        其中,head和tail表示链表的表头和表尾节点,len表示链表中节点的数目,dup、free、match分别为复制、释放和对比函数。

    b, 场景

        链表结构的特点是可以快速的在表头和表尾插入和删除元素,但查找复杂度高,是列表的底层实现之一,也因此列表没有提供判断某一元素是否在列表中的借口,因为在链表中查找复杂度高。

 

3,字典

    redis的字典使用哈希表作为底层实现。

    a, 结构

        上图为字典结构图

        dict结构中,type表示是dicttype类型的指针,表示操作特定类型的键值对的函数,privdata是传给特定函数的可选参数。ht是包含两个哈希表的数组,ht[0]表示正常存放数据的hash表,而ht[1]用于rehash,rehashidx是记录了rehash的进度,正常情况下为-1。

        dictht是哈希表,table表示哈希表数组,指针数组,size表示哈希表的大小,used表示已有节点的数目,used/size为负载因子,决定何时进行rehash。sizemask用于计算索引值。

        每个哈希表元素是dictentry结构,key为键,value可以是一个指针或是一个整数。,next为指向下一个的指针。是传统的hash表。

    b, rehash

        redis使用murmurhash算法计算hash值,能有很好的随机分布性,速度也很快。

        当负载因子大于3/2时进行扩容操作,扩容大小为第一个大于ht[0].used*2的2^n,当负载因子小于0.1进行缩容,为第一个大于ht[0].used的2^n。

        redis采用渐进式rehash,将rehash操作分摊到每次增删改查,具体过程见这里

    c, 场景

        字典是数据库和哈希对象的底层实现,数据库中dict存放所有kv,v可能是各种对象,而expire存放有过期时间的k和过期时间。用作hash底层时,k和v都是字符串对象。

4,跳跃表

    跳跃表是一种可以快速访问节点的数据结构,性能接近于平衡术,且实现简单。

    a, 结构

        跳跃链表是一种随机化数据结构,基于并联的链表。跳跃列表是对有序的链表增加上附加的前进链接,增加是以随机化的方式进行的,所以在列表中的查找可以快速的跳过部分列表。所有操作都以对数随机化的时间进行。

        header和tail指向表头和表尾,level表示最大层级,length表示节点数目(不包括首节点)

        每个节点都包含一个后退指针,用于从尾部遍历,路径唯一。obj为一个对象,score为对应的分值。level是大小随机出来的层级数组,每个层级包含一个前进指针和距离指向节点的跨度。跨度用于计算rank,跨度之和为rank。具体算法这里不介绍,具体见这里

    b, 场景

        跳跃表是有序集合的底层实现之一,跳跃表将指向有序集的 score 值和 member 域的指针作为元素, 并以 score 值为索引, 对有序集元素进行排序。  

        插入节点的流程:从表头指定的当前最大深度开始,逐层遍历找到节点插入的位置,rank数组记录的是沿途跨国的节点的跨度,即本层上一节点之前的跨度和,update数组记录的是在该层插入节点的位置,即上一个节点,之后取随机的层数初始化节点,若该层数大于当前的总层数则将层数更新对于这些大于之前的层数小于新层数之间的更新rank为0且update为头结点,之后从0开始到新节点的最大层逐层遍历将节点插入到update记录的节点之后,并更新span

        redis根据自己的需求对跳跃表做了更改:

  1. score 值可重复。
  2. 对比一个元素需要同时检查它的 score 和 memeber 。
  3. 每个节点带有高度为 1 层的后退指针,用于从表尾方向向表头方向迭代,当执行ZREVRANGE或 ZREVRANGEBYSCORE 这类以逆序处理有序集的命令时,就会用到这个属性。

5,整数集合

    redis的整数集合实质上是动态的数组。reids的整数集合是可以根据整数的值,自动选择用什么长度来存储。

    a, 结构 

        encoing标会编码方式,8/16/32/64位,length表示集合元素的数量,contents表示数据,元素由小到大排列。 

    b, 升级

        当加入的数大于encoding对应的最大长度时,自动进行升级操作。流程是:首先扩展数组空间的大小。将原数组中的原书进行类型扩展并存储,最后将新插入的数放入对应位置。整数集合不做降级操作。

    c, 场景

        整数集合是redis集合对象的底层实现之一。当键数量小于512并且键值为整数时集合使用整数集合作为底层存储,节约内存。如何保证不重复?(待解决)。

 

6,压缩列表

redis使用压缩列表来存储小整数值或长度比较短的字符串

    压缩列表是为了节省内存开发的,是一系列特殊编码的连续内存块组成的顺序型数据结构。

    a, 结构

        zlbytes记录整个列表所占的内存数

        zltail记录距离尾节点的距离

        zllen记录节点数目

        entry是每个节点

        zlend列表结束标志

        每个节点的组成,previous_entry_length是前一节点的长度,可用于从尾节点向前遍历,encoding记录content的数据类型和长度,content为节点的值。

    b, 连锁更新

        当插入或者删除元素时,会导致previous_entry_length的长度发生变化,如有1子节点为5字节,如果原先本节点的总大小处于250至253之间,会导致笑一个节点的previous..的长度发生变化,可能引起连锁更新的情况。需要不停的重复分配空间来存放增大的大小。

        但redis中假定的是处于临界大小的数据很多并且连续这种情况几率很低,同事假定被更新的节点数目少。

    c, 场景

        redis使用压缩列表来作为列表键和哈希键的底层实现之一,存储小整数值或长度比较短的字符串时使用,previous_entry_length的存在使其可以像链表一样遍历。实现hash时顺序添加相邻接的节点为k和v。

  • 大小: 5.7 KB
  • 大小: 17.8 KB
  • 大小: 34.3 KB
  • 大小: 41.6 KB
  • 大小: 9.2 KB
  • 大小: 3.3 KB
  • 大小: 3.1 KB
分享到:
评论

相关推荐

    redis基础数据结构讲解

    本文主要介绍redis的几种数据类型和适用场景。会列出简单例子,具体的redis函数不会一一介绍。不过这些简单的例子基本上满足80%以上的项目。

    redis面试题.txt

    Redis支持以下几种数据结构: - 字符串(String):最基本的数据结构,可以存储字符串、整数或浮点数。 - 哈希表(Hash):类似于字典,可以存储多个键值对。 - 列表(List):有序的字符串列表,可以进行插入、删除...

    redisStudy.zip

    加分项:另外redis还对这几种数据结构做了扩展,如GEO对位置计算,hyperLogLog做统计,bitmaps:redis底层存储value值都是存储的二进制数据,redis提供bitmaps(位图)可以直接访问或修改底层存储的二进制数据 ...

    redis中的数据结构和编码详解

    本文主要和大家分享几种Redis数据结构详解,希望文中的案例和代码,能帮助到大家。

    redis开发的概要介绍与分析

    数据结构:Redis支持多种数据结构,包括字符串(strings)、列表(lists)、集合(sets)、有序集合(sorted sets)以及哈希(hashes),这些丰富的数据结构为开发者提供了灵活的数据存储和处理方式。 持久化方式:...

    Java面试题比较全的知识点总结.docx

    1.什么是Redis? 答:Remote Dictionary Server(Redis)是一个...如果你是Redis中高级用户,还需要加上下面几种数据结构HyperLogLog、Geo、Pub/Sub。如果你说还玩过Redis Module,像BloomFilter,RedisSearch,Redis-ML

    数据持久化方案redisDB.zip

    以及incr 格式, mysql表结构不需要自己定义,系统自动映射 消息队列采用无锁队列, 支持mmap与malloc两种方式, 采用mmap方式理论上在程序意外死掉的时候不丢失队列数据 经过压力测试, 修改前和修改后的redis性能损耗...

    Redis学习手册

    在目前的版本中,Redis 除了Key/Value 之外还支持 List、Hash、Set 和Ordered Set 等数据结构,因 此它的用途也更为宽泛。对于此种误解,Redis 官网也进行了相应的澄清。和以上两种产品不同的是,Redis 的 License ...

    Redis的面试题

    1.什么是Redis? 答:Remote Dictionary Server...如果你是Redis中高级用户,还需要加上下面几种数据结构HyperLogLog、Geo、Pub/Sub。 如果你说还玩过Redis Module,像BloomFilter,RedisSearch,Redis-ML 3.Redis的

    使用Redis实现微信步数排行榜功能

    碰巧,在3月份找工作面试时,有个面试官先问了我Redis有哪几种数据结构,在我讲完后,面试官又问了我以下问题: 如何用Redis实现微信步数排行榜? 相信很多小伙伴都知道,可以使用Redis的有序集合ZSET来实现,本篇...

    Java面试整理,涵盖基础、JVM、线程并发、框架、MySQL、微服务、Redis、中间件、数据结构与算法等。陆续完善中.zip

    Java的主要特点和优势包括以下几个方面: 跨平台性(Write Once, Run Anywhere): Java的代码可以在不同的平台上运行,只需编写一次代码,就可以在任何支持Java的设备上执行。这得益于Java虚拟机(JVM),它充当了...

    解锁redis锁的正确姿势

    锁在redis中最简单的数据结构就是string。最早的时候,上锁的操作一般使用setnx,这个命令是当:lock不存在的时候set一个val,或许你还会记得使用expire来增加锁的过期,解锁操作就是使用del命令,伪代码如下: if ...

    Python 用Redis简单实现分布式爬虫的方法

    Redis通常被认为是一种持久化的存储器关键字-值型存储,可以用于几台机子之间的数据共享平台。 连接数据库 注意:假设现有几台在同一局域网内的机器分别为...Redis含列表、集合,字符串等几种数据结构,具体详细

    Python+Redis实现布隆过滤器

     通过一种叫作散列表(又叫哈希表,Hash table)的数据结构。它可以通过一个Hash函数将一个元素映射成一个位阵列(Bit array)中的一个点。这样一来,我们只要看看这个点是不是1就可以知道集合中有没有它了 布隆...

    详解centos7 yum安装redis及常用命令

    Redis是一种基于内存的数据结构存储,可持久化的日志型、Key-Value数据库。使用关系型数据库的站点达到一定并发量的时候,往往在磁盘IO上会有瓶颈,这时候配合redis就有一定的优势,因为它具有以下几个特性: 基于...

    安装Redis就那么几步,很简单

    Redis是一种非关系型数据库(NoSQL),NoSQL是以key-value的形式存储,和传统的关系型数据库不一样,不一定遵循传统数据库的一些基本要求,比如说SQL标准,ACID属性,表结构等等,这类数据库主要有以下特点:非关系...

    leetcode下载-JavaTopic:Java面试题总结

    redis的有几种集群方式; redis的基本数据类型(String、List、Hash、Set、ZSet)的使用场景? redis集群; redis支持事务吗?如果不支持,如果保证事务一致性? Java篇: Java线程池初始化的几个核心参数及其作用 ...

    天涯社区开源的NoSQL数据库 Memlink.zip

    (大约是redis几倍),同时使用了redo-log技术保证数据的持久化。Memlink还支持主从复制、读写分离、List过滤操作等功能。 与Memcached不同的是,它的value是一个list/queue。并且提供了诸如持久化,分布式的功能。听...

    基于 gin+gorm+redis+mysql 读写分离的电子商城.zip

    它完全支持结构化查询语言(SQL),允许用户进行数据查询、插入、更新、删除、创建和管理数据库结构等操作。SQL标准的广泛支持使得MySQL易于学习,且与其他关系型数据库系统有良好的互操作性。 存储引擎 MySQL支持...

Global site tag (gtag.js) - Google Analytics