一、Redis基本数据结构介绍

本文参考书籍:《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
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345