美文网首页
一、Redis基本数据结构介绍

一、Redis基本数据结构介绍

作者: Suny____ | 来源:发表于2020-08-04 17:04 被阅读0次

    本文参考书籍:《Redis开发与运维》

    1、Redis的作用

    • 共享session
    • 计数器
    • 排行榜
    • 消息队列
    • 社交
    • 限速
    • 缓存
    • 分布式锁

    2、Redis可执行文件说明

    可执行文件 作用
    redis-server 启动Redis
    redis-cli Redis命令行客户端
    redis-benchmark Redis基准测试工具
    redis-check-aof Redis AOF持久化文件检测和修复工具
    redis-check-dump Redis RDB持久化文件检测和修复工具
    redis-sentinel 启动Redis Sentinel

    Redis版本号第二位按奇偶分为开发版本和稳定版本,如2.9、3.1这样就是开发版本,3.0、3.2就是稳定版本

    3、Redis对外的数据结构和内部编码

    通过object encoding <key> 查询内部编码


    image.png

    Redis客户端每次执行命令都经过了三个阶段:发送命令、执行命令、返回结果

    image.png

    因为Redis是单线程执行命令,所以一条命令从客户端到服务端不会立即执行,所有命令都会进入一个队列,然后逐条被执行,不会存在同时执行多条命令的情况。

    image.png

    Redis单线程架构

    Redis使用了单线程架构和I/O多路复用模型来实现高性能的内存数据库服务


    image.png

    为什么单线程模型性能如此高

    • 纯内存访问,Redis将所有数据放在内存中,内存的响应时长大概为100纳秒,这是Redis达到每秒万级别访问的重要基础
    • 非阻塞I/O,Redis使用epoll作为I/O多路复用技术的实现,再加上Redis自身的事件处理模型将epoll中的连接、读写、关闭都转换为事件,不用再网络I/O上浪费过多的时间。
    • 单线程避免了线程切换和竞态产生的消耗
      • 单线程可以简化数据结构和算法的实现。
      • 单线程避免了线程切换和竞态的消耗
        Redis是面向快速执行场景的数据库,每个命令的执行时间不能过长。

    4、Redis基础数据结构

    image.png

    字符串(string)

    字符串是Redis中最基础的数据结构,其他几种数据结构都是在字符串类型的基础上构建的。
    字符串的值实际可以是字符串(简单的字符串、复杂的字符串(JSON、XML))、数字(整数、浮点),甚至是二进制(图片、音频、视频),但是值最大不能超过512MB。

    image.png
    • 字符串的内部编码有三种:
      • int:8个字节的长整形
      • embstr:小于等于39个字节的字符串
      • raw:大于39个字节的字符串
      • Redis会根据当前值的类型和长度决定使用哪种内部编码实现

    使用场景:

    • 计数器
    • 限速
      image.png

    哈希(hash)

    哈希类型是指键值本身又是一个键值对结构。
    哈希类型中的映射关系叫做field-value,这里的value是指field对应的值,不是键对应的值。


    image.png

    哈希的内部编码有两种:

    • ziplist(压缩列表)
      • 当哈希类型元素个数小于hash-max-ziplist-entries配置(512个)、同时所有值都小于hash-max-ziplist-value配置(64字节)时,Redis会使用ziplist作为哈希的内部实现,ziplist使用更加紧凑的结构实现多个元素的连续存储,所以在节省内存方面比hashtable优秀。
    • hashtable(哈希表)
    • 当哈希类型无法满足ziplist的条件时,Redis会使hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降,而hashtable的读写时间复杂度为O(1)。
      当field个数超过512或有value大于64字节,内部编码都会变成hashtable。

    使用场景:

    可以存储用户信息,使用哈希类型存储会变得更加直观,操作也更加便捷。同样的用户信息存在关系型数据库和Redis中的哈希结构对比:
    一、哈希类型是稀疏的,而关系型数据库是完全结构化的。例如:哈希类型每个键都可以有不同的field,而关系型数据库一旦添加新列,所有行都要为其设置值(即使为null)。

    image.png

    二、关系型数据库可以做复杂的关系查询,而Redis去模拟关系型复杂查询开发困难,维护成本高。

    • 哈希类型优点:

      • 简单直观,使用合理可以减少内存空间的使用
    • 哈希类型缺点:

      • 要控制哈希在ziplist和hashtable两种内部编码的转换,hashtable会消耗更多内存
    image.png

    列表(list):

    列表类型是用来存储多个有序的字符串,列表中的每个字符串称为元素(element),一个列表最多可以存储2^32 - 1个元素。

    可以对列表两端插入(push)和弹出(pop),还可以获取指定范围的元素列表、获取指定索引下的元素等。

    列表是一种比较灵活的数据结构,它可以充当栈和队列的角色。

    image.png

    列表类型的特点:

    • 列表中的元素是有序的
    • 列表中的元素可以是重复的

    列表的内部编码有两种:

    • ziplist(压缩列表)
      • 当元素个数小鱼list-max-ziplist-entries配置(512个),同时列表中每个元素的值都小于list-max-ziplist-value配置(64字节)时,Redis会选用ziplist来作为列表的内部实现来减少内存的使用。
    • linkedlist(链表)
      • 当列表类型无法满足ziplist条件时,Redis会使用linkedlist作为列表的内部实现。
        Redis3.2版本提供了quicklist内部编码,它是以一个ziplist为节点的linkedlist,结合了ziplist和linkedlist两者的优势,为列表类型提供了一种更为优秀的内部编码实现。

    使用场景:

    • 消息队列
      • Redis的lpush+brpop命令组合即可实现阻塞队列,生产者客户端lpush从列表左侧插入元素,多个消费者客户端使用brpop命令阻塞式的“抢”列表尾部的元素,多个客户端保证了消费的负载均衡和高可用性。
      • lpush+brpop=message queue(消息队列)
        image.png
    • 文章列表
      • 每个用户有属于自己的文章列表,现需分页展示文章列表。此刻可以考虑使用列表,因为列表不但是有序的,同时支持按索引范围获取元素。
      • 使用列表类型保存和获取文章列表会存在两个问题:
        • 如果每次分页获取的文章个数多,需要执行多次hgetall操作,此时可以考虑使用pipeline批量获取。
        • 分页获取文章列表时,lrange命令在列表两端性能较好,但是如果列表较大,获取列表中间范围的元素性能会变差,此时可以考虑将列表做成二级拆分,或者使用Redis3.2的quicklist内部编码实现。

    实际列表的使用场景很多,在选择时可以参考以下组合:

    • lpush+lpop=Stack(栈)
    • lpush+rpop=Queue(队列)
    • lpush+ltrim=capped collection(有限集合)
      image.png

    集合(set)

    集合类型也是用来保存多个的字符串元素,但和列表类型不一样的是,集合中不允许有重复元素,并且集合中的元素是无序的,不能通过索引填表获取元素。

    一个集合最多可以存储2^32 - 1个元素。Redis除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集。

    image.png

    集合类型的内部编码有两种:

    • intset(整数集合)
      • 当即和中的元素都是整数且元素个数小于set-max-intset-entries配置(512个)时,Redis会选用intset作用集合的内部实现,从而减少内存的使用。
    • hashtable(哈希表)
      • 当集合类型无法满足intset条件时,Redis会使用hashtable作为集合的内部实现。

    使用场景:

    集合类型比较典型的使用场景是标签(tag)。例如一个用户可能对娱乐、体育比较感兴趣,另一个用户可能对历史、新闻感兴趣,这些兴趣点就是标签。有了这些数据就可以得到喜欢同一个标签的人,以及用户的共同洗好的标签,这些数据对于用于体验以及增强用户黏度比较重要。可以对不同标签的用户做不同类型的推荐。


    image.png

    代码例子:

    • 给用户添加标签
    sadd user:1:tags tag1 tag2
    sadd user:2:tags tag2 tag3
    ....
    sadd user:n:tags tag5 tag6
    
    • 给标签添加用户
    sadd tag1:users user1 user2
    sadd tag2:users user2 user3
    ...
    

    用户和标签的关系应该维护在一个事务里,防止部分命令失败造成的数据不一致。

    • 计算用户共同感兴趣的标签
    sinter user:1:tags user:2:tag2
    

    使用集合类型的应用场景可以参考如下几点:

    • sadd=tagging(标签)
    • spop/srandmember=random item(生成随机数,比如抽奖)
    • sadd+sinert=social graph(社交需求)
      image.png

    有序集合(zset)

    有序集合保留了集合不能重复成员的特性,但有序集合中的元素可以排序。但是它与列表的排序不同,它给每个元素设置一个分数(score)作为排序的依据。

    有序集合提供了获取指定分数和元素范围查询、计算成员排名等功能。

    image.png

    有序集合类型的内部编码有两种:

    • ziplist(压缩列表)
      • 当有序集合的元素个数小于zset-max-ziplist-entries配置(128个),同时每个元素的值都小于zset-max-ziplist-value配置(64字节)时,Redis会用ziplist来作为有序集合的内部实现。
    • skiplist(跳跃表)
      • 当ziplist条件不满足时,有序集合会使用skiplist作为内部实现。
    image.png

    使用场景:

    有序集合典型的使用场景是排行榜系统。例如:视频网站需要对用户上传视频做排行榜,榜单的维度可能是多个方面的:按时间、按播放量、按获得的赞数等。


    image.png

    相关文章

      网友评论

          本文标题:一、Redis基本数据结构介绍

          本文链接:https://www.haomeiwen.com/subject/xopwrktx.html