Redis高可用系列——Set类型底层详解

这篇具有很好参考价值的文章主要介绍了Redis高可用系列——Set类型底层详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

Redis是一种高性能的键值型数据库,它支持多种数据结构,其中一种是set类型。set类型可以存储一个无序的、不重复的字符串集合,类似于Java中的HashSet或Python中的set。set类型的优点是可以对集合进行快速的添加、删除、判断是否存在等操作,以及对多个集合进行交集、并集、差集等操作。


set

概述

在讲解set结构之前,需要先说明一下set结构编码的更替,如下

  • Redis7.2之前,set使用的是intsethashtable
  • Redis7.2之后,set使用的是intsetlistpackhashtable

intset

intset是一种紧凑的数组结构,它只保存int类型的数据,它将所有的元素按照从小到大的顺序存储在一块连续的内存中。intset会根据传入的数据大小,encoding分为int16_tint32_tint64_t

Redis高可用系列——Set类型底层详解
下图为命令所显示的编码结构

127.0.0.1:6379> sadd set 123
(integer) 1
127.0.0.1:6379> object encoding set
"intset"
127.0.0.1:6379> sadd set abcd
(integer) 1
127.0.0.1:6379> object encoding set
"hashtable"

intset 和 hashtable 的转换

Redis7.2之前,当一个集合满足以下两个条件时,Redis 会选择使用intset编码:

  • 集合对象保存的所有元素都是整数值
  • 集合对象保存的元素数量小于等于512个(默认)

intset最大元素数量可在redis.conf配置

set-max-intset-entries 512

为什么加入了listpack

redis7.2之前,sds类型的数据会直接放入到编码结构式为hashtableset中。其中,sds其实就是redis中的string类型。

而在redis7.2之后,sds类型的数据,首先会使用listpack结构当 set 达到一定的阈值时,才会自动转换为hashtable

添加listpack结构是为了提高内存利用率和操作效率,因为 hashtable 的空间开销和碰撞概率都比较高。

hashtable 的空间开销高

hashtable 的空间开销高是因为它需要预先分配一个固定大小的数组来存储键值对,而这个数组的大小通常要大于实际存储的元素个数,以保证较低的装载因子。装载因子是指 hashtable 中已经存储的元素个数和数组大小的比值,它反映了 hashtable 的空间利用率

  • 如果装载因子过高,那么 hashtable 的性能会下降,因为碰撞的概率会增加
  • 如果装载因子过低,那么 hashtable 的空间利用率会下降,因为数组中会有很多空闲的位置

因此,hashtable 需要在装载因子和空间利用率之间做一个平衡,通常装载因子的推荐值是 0.75

hashtable 的碰撞概率高

hashtable碰撞概率高是因为它使用了一个散列函数来将任意长度的键映射到一个有限范围内的整数,作为数组的索引

散列函数的设计很重要,它应该尽可能地保证不同的键能够均匀地分布在数组中,避免出现某些位置过于拥挤,而其他位置过于稀疏的情况。然而,由于散列函数的输出范围是有限的,而键的取值范围是无限的,所以不可能完全避免两个不同的键被散列到同一个位置上,这就产生了碰撞。碰撞会影响 hashtable 的性能,因为它需要额外的处理方式来解决冲突,比如开放寻址法或者链地址法

举例说明,假设有一个大小为8的hashtable,使用取模运算作为散列函数,即h(k) = k mod 8。现在有四个键:5,13,21,29,它们都被散列到索引1
Redis高可用系列——Set类型底层详解
这就是一个碰撞的例子,因为四个键都映射到了同一个索引。这种情况可能是由于以下原因造成的:

  • 散列函数的选择不合适,没有充分利用hashtable的空间。
  • 键的分布不均匀,有些区间的键出现的频率更高。
  • hashtable的大小太小,不能容纳所有的键。

为了解决碰撞,redis采用了链地址法。就是在每个索引处维护一个链表,存储所有散列到该索引的键。但是,如果链表过长,查找效率会降低。因此,一般建议保持hashtable的负载因子(即键的数量除以hashtable的大小)在一定范围内,比如0.5到0.75之间。如果负载因子过高或过低,可以通过扩容或缩容来调整hashtable的大小

intset 、listpack和hashtable的转换

intset 、listpack和hashtable这三者的转换时根据要添加的数据、当前set的编码和阈值决定的。

  • 如果要添加的数据是整型,且当前set的编码为intset,如果超过阈值由intset直接转为hashtable

    阈值条件为:
    set-max-intset-entriesintset最大元素个数,默认512

  • 如果要添加的数据是字符串,分为三种情况

    • 当前set的编码为intset:如果没有超过阈值,转换为listpack;否则,直接转换为hashtable
    • 当前set的编码为listpack:如果超过阈值,就转换为hashtable
    • 当前set的编码为hashtable:直接插入,编码不会进行转换

    阈值条件为:
    set-max-listpack-entries:最大元素个数,默认128
    set_max_listpack_value:最大元素大小,默认64
    以上两个条件需要同时满足才能进行编码转换


总结

Redis set类型是一种可以存储一个无序的、不重复的字符串集合的数据结构,它有以下特点:

  • 可以对集合进行添加、删除、判断是否存在等操作,时间复杂度都是O (1)
  • 可以对多个集合进行交集、并集、差集等操作,时间复杂度和集合元素个数有关
  • 可以用作标签、好友关系、共同爱好等场景

系列文章目录

Redis内存优化——String类型介绍及底层原理详解
Redis内存优化——Hash类型介绍及底层原理详解
Redis内存优化——List类型介绍及底层原理详解
Redis内存优化——Set类型介绍及底层原理详解
Redis内存优化——ZSet类型介绍及底层原理详解
Redis内存优化——Stream类型介绍及底层原理详解
Redis内存优化——Hyperloglog、GEO、Bitmap、Bitfield类型详解
Redis的三种持久化策略及选取建议文章来源地址https://www.toymoban.com/news/detail-437481.html

到了这里,关于Redis高可用系列——Set类型底层详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • redis十种数据类型及底层原理

    Redis 是一个开源的高性能键值数据库,它支持多种数据类型,可以满足不同的业务需求。本文将介绍 Redis 的10种数据类型,分别是 string(字符串) hash(哈希) list(列表) set(集合) zset(有序集合) stream(流) geospatial(地理) bitmap(位图) bitfield(位域) hyperloglog(基

    2024年02月12日
    浏览(43)
  • Redis带你深入学习数据类型set

    目录 1、set 2、set相关命令 2.1、添加元素 sadd 2.2、获取元素 smembers 2.3、判断元素是否存在 sismember 2.4、获取set中元素数量 scard 2.5、删除元素spop、srem 2.6、移动元素smove 2.7、集合中相关命令:sinter、sinterstore、sunion、sunionstore、sdiff、sdiffstore 3、应用场景 set数据类型的特点: s

    2024年02月09日
    浏览(44)
  • Redis追本溯源(二)数据结构:String、List、Hash、Set、Zset底层数据结构原理

    Redis 并没有直接用 C 语言的字符串,而是自己搞了一个 sds 的结构体来表示字符串,这个 sds 的全称是 Simple Dynamic String,翻译过来就是“简单的动态字符串”。 安全的二进制存储 资源。关于sds的扩容和缩容下面会进行详细的介绍,这里先不赘述了。 在一些情况中,我们需要

    2024年02月16日
    浏览(51)
  • 11_Redis经典五大类型源码及底层实现

    SDS 动态字符串 双向链表 压缩列表 zpilist 哈希表 hashtable 调表 skiplist 整数集合 intset 快速列表 quicklist 紧凑列表 listpack Github:https://github.com/redis/redis Redis设计与实现 Redis5设计与源码分析 4.1 源码分析思路 怎么看 外面考什么,看什么 分类 4.2 Redis基本的数据结构(骨架) 简单动

    2024年02月11日
    浏览(35)
  • 聊一聊redis十种数据类型及底层原理

    Redis 是一个开源的高性能键值数据库,它支持多种数据类型,可以满足不同的业务需求。本文将介绍 Redis 的10种数据类型,分别是 string(字符串) hash(哈希) list(列表) set(集合) zset(有序集合) stream(流) geospatial(地理) bitmap(位图) bitfield(位域) hyperloglog(基

    2024年02月03日
    浏览(47)
  • Redis之数据类型String、List、Hash、Set、Sorted Set(详细)

    一、String数据类型 1、SET/GET/APPEND/STRLEN (1) APPEND (2) SET/STRLEN 2、 INCR/ DECR/INCRBY/DECRBY (1)INCR/ DECR (2) INCRBY/DECRBY INCRBY key increment:key值增加指定的整数DECRBY key decrement:key值减少指定的整数  3、GETSET 4、 SETEX  5、SETNX 6、MSET/MGET/MSETNX  二、List数据类型 1、LPUSH/LPUSHX/

    2024年02月11日
    浏览(42)
  • Redis数据类型(list\set\zset)

    \\\"maybe it\\\'s why\\\"          列表类型是⽤来存储多个 有序 的字符串,列表中的每个字符串称为元素(element),⼀个列表最多可以存储个2^32 - 1个元素。在Redis中,可以对列表两端插⼊(push)和弹出(pop),还可以获取指定范围的元素列表、获取指定索引下标的元素等。列表是

    2024年02月11日
    浏览(41)
  • 【Redis】1、学习 Redis 的五大基本数据类型【String、Hash、List、Set、SortedSet】

    🍀 Redis 诞生于2009年,全称是 Re mote D ictionary S erver,远程字典服务器,是一个基于 内存的键值型 NoSQL 数据库 🍀 键值(key-value)型,value 支持多种不同数据结构,功能丰富 🍀 单线程,每个命令具备 原子性 🍀 低延迟,速度快(基于内存、IO 多路复用、良好的编码) 🍀支

    2024年02月11日
    浏览(39)
  • Redis的五种数据类型(string、hash 、list、set、zset)

                     Redis 提供了丰富的数据类型,常见的有五种: String(字符串),Hash(哈希),List(列表),Set(集合)、Zset(有序集合) 。         String 是最基本的 key-value 结构,key 是唯一标识,value 是具体的值,value其实不仅是字符串, 也可以是数字(整

    2024年01月25日
    浏览(49)
  • 【Redis从头学-7】Redis中的Set数据类型实战场景之用户画像去重、共同关注、专属粉丝

    🧑‍💻作者名称:DaenCode 🎤作者简介:啥技术都喜欢捣鼓捣鼓,喜欢分享技术、经验、生活。 😎人生感悟:尝尽人生百味,方知世间冷暖。 📖所属专栏:Redis从头学 之前的篇章对Redis的String、List、Hash数据类型已经做出了具体分析,并举例说明了其具体的实战场景本文就

    2024年02月12日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包