皇冠体育寻求亚洲战略合作伙伴,皇冠代理招募中,皇冠平台开放会员注册、充值、提现、电脑版下载、APP下载。

首页快讯正文

usdt法币交易api接口(www.caibao.it):统一份数据,Redis为什么要存两次

admin2021-03-0924

USDT自动充值接口

菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。

原题目:统一份数据,Redis为什么要存两次

前言

在 Redis 中,有一种数据类型,当在存储的时刻会同时接纳两种数据结构来举行划分存储,那么 Redis 为什么要这么做呢?这么做会造成统一份数据占用两倍空间吗?

五种基本类型之聚集工具

Redis 中的聚集工具是一个包罗字符串类型元素的无序聚集,聚集中元素唯一不能重复。

聚集工具的底层数据结构有两种: intset 和 hashtable 。内部通过编码来举行区分:

编码属性 形貌 object encoding下令返回值
OBJ_ENCODING_INTSET 使用整数聚集实现的聚集工具 intset
OBJ_ENCODING_HT 使用字典实现的聚集工具 hashtable
intset 编码

intset (整数聚集)可以保留类型为 int16_t , int32_t , int64_t 的整数值,而且保证聚集中没有重复元素。

intset 数据结构界说如下(源码 inset.h 内):

{

encoding;

length;

contents[];

} intset;

下图就是一个 intset 的聚集工具存储简图:

encoding

在 intset 内部的 encoding 纪录了当前整数聚集的数据存储类型,主要有三种:

contents[]

contents[] 虽然结构的界说上写的是 int8_t 类型,然则现实存储类型是由上面的 encoding 来决议的。

整数聚集的升级

若是一更先整数聚集中的元素都是 16 位的,接纳 int16_t 类型来存储,此时需要再存储一个 32 位的整数,那么就需要对原先的整数聚集举行升级,升级之后才气将 32 位的整数存储到整数聚集内。这就涉及到了整数聚集的类型升级,升级历程主要有 4 个步骤:

  1. 将现有的元素举行类型转换,并将转换类型后的元素从后到前逐个重新放回到数组内。
  2. 将新元素放到数组的头部或者尾部(由于触发升级的条件就是当前数组的整数类型无法存储新元素,以是新元素要么比现有元素都大,要么就比现有元素都小)。
  3. 将 encoding 属性修改为最新的编码,而且同步修改 length 属性。

PS: 和字符串工具的编码一样,整数聚集的类型一旦发生升级,将会保持编码,无法降级

升级示例

  1. 若是我们有一个聚集存储的 encoding 是 int16_t ,内部存储了 3 个元素:
  2. 这时刻需要插入一个整数 50000 ,发现存储不下去,而 50000 是一个 int32_t 类型整数,以是需要申请新空间,申请空间巨细为 4 * 32 - 48=80 。

  1. 现在新的数组内要放置 4 个元素,原来的数组排在第 3 ,以是需要将升级后的 3 移动到 64-95 位。

  1. 继续将升级后的 2 移动到 32-63 位。

  1. 继续将升级后的 1 移动到 0-31 位。

  1. 然后会将 50000 放到 96-127 位。

  1. 最后会修改 encoding 和 length 属性,修改之后就完成了本次的升级。
hashtable 编码 intset 和 hashtable 编码转换

当一个聚集知足以下两个条件时, Redis 会选择使用 intset 编码:

  • 聚集工具保留的所有元素都是整数值。
  • 聚集工具保留的元素数目小于即是 512 个(这个阈值可以通过设置文件 set-max-intset-entries 来控制)。 一旦聚集中的元素不知足上面两个条件,则会选择使用 hashtable 编码。
聚集工具常用下令
  • sadd key member1 member2:将一个或多个元素 member 加入到聚集 key 当中,并返回添加乐成的数目,若是元素已存在则被忽略。
  • si *** ember key member:判断元素 member 是否存在聚集 key 中。
  • srem key member1 member2:移除聚集 key 中的元素,不存在的元素会被忽略。
  • *** ove source dest member:将元素 member 从聚集 source 中移动到 dest 中,若是 member 不存在,则不执行任何操作。
  • *** embers key:返回聚集 key 中所有元素。

了解了操作聚集工具的常用下令,我们就可以来验证下前面提到的哈希工具的类型和编码了,在测试之前为了防止其他 key 值的滋扰,我们先执行 flushall 下令清空 Redis 数据库。

依次执行如下下令:

sadd num 1 2 3

type num

object encoding num

sadd name 1 2 3 test

type name

object encoding name

获得如下效果:

可以看到,当设置的元素内里只有整数时,聚集使用的就是 intset 编码,当设置的元素中含有非整数时,使用的就是 hashtable 编码。

五种基本类型之有序聚集工具

Redis 中的有序聚集和聚集的区别是有序聚集中的每个元素都市关联一个 double 类型的分数,然后凭据分数从小到大的顺序举行排列。换句话说,有序聚集的顺序是由我们自己设值的时刻通过分数来确定的。

有序聚集工具的底层数据结构有两种: skiplist 和 ziplist 。内部同样是通过编码来举行区分:

编码属性 形貌 object encoding下令返回值
OBJ_ENCODING_SKIPLIST 使用跳跃表实现的有序聚集工具 skiplist
OBJ_ENCODING_ZIPLIST 使用压缩列表实现的有序聚集工具 ziplist
skiplist 编码

skiplist 即跳跃表,有时刻也简称为跳表。使用 skiplist 编码的有序聚集工具使用了 zset 结构来作为底层实现,而 zset 中同时包罗了一个字典和一个跳跃表。

跳跃表

跳跃表是一种有序的数据结构,其主要特点是通过在每个节点中维持多个指向其他节点的指针,从而到达快速接见节点的目的。

大部分情况下,跳跃表的效率可以等同于平衡树,然则跳跃表的实现却远远比平衡树的实现简朴,以是 Redis 选择了使用跳跃表来实现有序聚集。

下图是一个通俗的有序链表,我们若是想要找到 35 这个元素,只能从头更先遍历到尾( 链表中元素不支持随机接见,以是不能用二分查找,而数组中可以通过下标随机接见,以是二分查找一样平常适用于有序数组),时间复杂度是 O(n) 。

那么若是我们可以直接跳到链表的中心,那就可以节约许多资源了,这就是跳表的原理,如下图所示就是一个跳表的数据结构示例:

,

Usdt第三方支付接口

菜宝钱包(www.caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。

,

上图中 level1 , level2 , level3 就是跳表的层级,每一个 level 层级都有一个指向下一个相同 level 层级元素的指针,好比上图我们遍历寻找元素 35 的时刻就有三种方案:

  • 第 1 种就是执行 level1 层级的指针,需要遍历 7 次(1->8->9->12->15->20->35)才气找到元素 35 。
  • 第 2 种就是执行 level2 层级的指针,只需要遍历 5 次(1->9->12->15->35)就能找到元素 35 。
  • 第 3 种就是执行 level3 层级的元素,这时刻只需要遍历 3 次(1->12->35)就能找到元素 35 了,大大提升了效率。
skiplist 的存储结构

跳跃表中的每个节点是一个 zskiplistNode 节点(源码 server.h 内):

{

sds ele;

score;

* ;

{

* ;

span;

} level[];

} zskiplistNode;

  • level(层)

level 即跳跃表中的层,其是一个数组,也就是说一个节点的元素可以拥有多个层,即多个指向其他节点的指针,程序可以通过差别层级的指针来选择最快捷的路径提升接见速率。

level 是在每次建立新节点的时刻凭据幂次定律(power law)随机天生的一个介于 1~32 之间的数字。

  • forward (前进指针)

每个层都市有一个指向链表尾部偏向元素的指针,遍历元素的时刻需要使用到前进指针。

  • span (跨度)

跨度纪录了两个节点之间的距离,需要注重的是,若是指向了 NULL 的话,则跨度为 0 。

  • backward (退却指针)

和前进指针不一样的是退却指针只有一个,以是每次只能退却至前一个节点(上图中没有画出退却指针)。

  • ele (元素)

跳跃表中元素是一个 sds 工具(早期版本使用的是 redisObject 工具),元素必须唯一不能重复。

  • score (分值)

节点的分值是一个 double 类型的浮点数,跳跃表中会将节点凭据分值凭据从小到大的顺序排列,差别节点的分值可以重复。

上面先容的只是跳跃表中的一个节点,多个 zskiplistNode 节点组成了一个 zskiplist 工具:

{

* , * ;

length;

level;

} zskiplist;

到这里你可能以为有序聚集就是用这个 zskiplist 来实现的,然而现实上 Redis 并没有直接使用 zskiplist 来实现,而是用 zset 工具再次举行了一层包装。

{

dict *dict;

zskiplist *zsl;

} zset;

以是最终,一个有序聚集若是使用了 skiplist 编码,其数据结构如下图所示:

上图中上面一部分中的字典中的 key 就是对应了有序聚集中的元素( member ), value 就对应了分值( score )。上图中下面一部分中跳跃表整数 1,8,9,12 也是对应了元素( member ),最后一排的 double 型数字就是分值( score )。

也就是说字典和跳跃表中的数据都指向了我们存储的元素( 两种数据结构最终指向的是统一个地址,以是数据并不会泛起冗余存储), Redis 为什么要这么做呢?

为什么同时选择使用字典和跳跃表

有序聚集直接使用跳跃表或者单独使用字典完全可以独自实现,然则我们想一下,若是单独使用跳跃表来实现,那么虽然可以使用跨度大的指针去遍历元素来找到我们需要的数据,然则其复杂度仍然到达了 O(logN) ,而字典中获取一个元素的复杂度是 O(1) ,而若是单独使用字典虽然获取元素很快,然则字典是无序的,以是若是要局限查找就需要对其举行排序,这又是一个耗时的操作,以是 Redis 综合了两种数据结构来更大水平的提升性能,这也是 Redis 设计的精妙之处。

ziplist 编码 ziplist 和 skiplist 编码转换

当有序聚集工具同时知足以下两个条件时,会使用 ziplist 编码举行存储:

  • 有序聚集工具中保留的元素个数小于 128 个(可以通过设置 zset-max-ziplist-entries 修改)。
  • 有序聚集工具中保留的所有元素的总长度小于 64 字节(可以通过设置 zset-max-ziplist-value 修改)。
有序聚集工具常用下令
  • zadd key score1 member1 score2 member2:将一个或多个元素( member )及其 score 添加到有序聚集 key 中。
  • zscore key member:返回有序聚集 key 中 member 成员的 score 。
  • zincrby key num member:将有序聚集 key 中的 member 加上 num , num 可以为负数。
  • zcount key min max:返回有序聚集 key 中 score 值在 [min,max] 区间的 member 数目。
  • zrange key start stop:返回有序聚集 key 中 score 从小到大排列后 在 [start,stop] 区间的所有 member 。
  • zrevrange key start stop:返回有序聚集 key 中 score 从大到小排列后 在 [start,stop] 区间的所有 member 。
  • zrangebyscore key min max:返回有序聚集中按 score 从小到大排列后在 [min,max] 区间的所有元素。注重这里 默认是闭区间,然则可以在 max 和 min 的数值前面加上 ( 或者 [ 来控制开闭区间 。
  • zrevrangebyscore key max min:返回有序聚集中按 score 从大到小排列后在 [min,max] 区间的所有元素。注重这里 默认是闭区间,然则可以在 max 和 min 的数值前面加上 ( 或者 [ 来控制开闭区间 。
  • zrank key member:返回有序聚集中 member 中元素排名(从小到大),返回的效果从 0 更先盘算。
  • zrevrank key member:返回有序聚集中 member 中元素排名(从大到小),返回的效果从 0 更先盘算。
  • zlexcount key min max:返回有序聚集中 min 和 max 之间的 member 数目。注重这个下令中的 min 和 max 前面 必须加 ( 或者 [ 来控制开闭区间 ,特殊值 - 和 + 划分示意负无限和正无限。

了解了操作有序聚集工具的常用下令,我们就可以来验证下前面提到的哈希工具的类型和编码了,在测试之前为了防止其他 key 值的滋扰,我们先执行 flushall 下令清空 Redis 数据库。

在执行下令之前,我们先把设置文件中的参数 zset-max-ziplist-entries 修改为 2 ,然后重启 Redis 服务

重启完成之后依次执行如下下令:

zadd name 1 zs 2 lisi

type name

object encoding name

zadd address 1 beijing 2 shanghai 3 guangzhou 4 shenzhen

type address

object encoding address

获得如下效果:

总结

网友评论

1条评论
  • 2021-04-11 00:05:07

    菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。有没有新人啊?