【Redis—基础】基本数据结构与应用

单线程模型

Redis使用了单线程架构I/O多路复用模型来实现高性能的内存数据库服务。每次Redis的客户端调用都经历了发送命令、执行命令、返回结果三个过程。因为Redis是单线程来处理命令的,所以一条命令从客户端达到服务端不会立刻被执行,所有命令都会进入一个队列中,然后逐个被执行。所以客户端命令的执行顺序是不确定的,但是可以确定不会有两条命令被同时执行,所以两条incr命令无论怎么执行最终结果都是2,不会产生并发问题,这就是Redis单线程的基本模型。但是像发送命令、返回结果、命令排队肯定不像描述的这么简单,Redis使用了I/O多路复用技术来解决I/O的问题。

为什么单线程还能这么快

通常来讲,单线程处理能力要比多线程差,那么为什么Redis使用单线程模型会达到每秒万级别的处理能力呢?可以将其归结为三点:第一,纯内存访问,Redis将所有数据放在内存中,内存的响应时长大约为100纳秒,这是Redis达到每秒万级别访问的重要基础。第二,非阻塞I/O,Redis使用epoll作为I/O多路复用技术的实现,再加上Redis自身的事件处理模型将epoll中的连接、读写、关闭都转换为事件,不在网络I/O上浪费过多的时间。第三,单线程避免了线程切换和竞态产生的消耗。既然采用单线程就能达到如此高的性能,那么也不失为一种不错的选择,因为单线程能带来几个好处:第一,单线程可以简化数据结构和算法的实现。如果对高级编程语言熟悉的读者应该了解并发数据结构实现不但困难而且开发测试比较麻烦。第二,单线程避免了线程切换和竞态产生的消耗,对于服务端开发来说,锁和线程切换通常是性能杀手。但是单线程会有一个问题:对于每个命令的执行时间是有要求的。如果某个命令执行过长,会造成其他命令的阻塞,对于Redis这种高性能的服务来说是致命的,所以Redis是面向快速执行场景的数据库。

基本数据结构和内部编码

        type命令返回当前键的数据结构类型,它们分别是:string(字符串)hash(哈希)list(列表)set(集合)zset(有序集合),但这些只是Redis对外的数据结构。实际上每种数据结构都有自己底层的内部编码实现,而且是多种实现,这样Redis会在合适的场景选择合适的内部编码。每种数据结构都有两种以上的内部编码实现,例如list数据结构包含了linkedlist和ziplist两种内部编码(3.2版本之前)。同时有些内部编码,例如ziplist,可以作为多种外部数据结构的内部实现,可以通过object encoding命令查询内部编码。

        Redis这样设计有两个好处:第一,可以改进内部编码,而对外的数据结构和命令没有影响,这样一旦开发出更优秀的内部编码,无需改动外部数据结构和命令,例如Redis3.2提供了quicklist,结合了ziplist和linkedlist两者的优势,为列表类型提供了一种更为优秀的内部编码实现,而对外部用户来说基本感知不到。第二,多种内部编码实现可以在不同场景下发挥各自的优势,例如ziplist比较节省内存,但是在列表元素比较多的情况下,性能会有所下降,这时候Redis会根据配置选项将列表类型的内部实现转换为linkedlist。

字符串

1.常用命令

【Redis—基础】基本数据结构与应用_第1张图片

2.内部编码

        字符串类型的内部编码有3种:

        ·int:8个字节的长整型。

        ·embstr:小于等于39个字节的字符串。

        ·raw:大于39个字节的字符串。

        Redis会根据当前值的类型和长度决定使用哪种内部编码实现。

3.使用场景

        缓存

        计数

        共享session、分布式锁

        限速

哈希

1.常用命令

【Redis—基础】基本数据结构与应用_第2张图片

【Redis—基础】基本数据结构与应用_第3张图片

2.内部编码

        哈希类型的内部编码有两种:

        ·ziplist(压缩列表):当哈希类型元素个数小于hash-max-ziplist-entries配置(默认512个)、同时所有值都小于hash-max-ziplist-value配置(默认64字节)时,Redis会使用ziplist作为哈希的内部实现,ziplist使用更加紧凑的结构实现多个元素的连续存储,所以在节省内存方面比hashtable更加优秀。

        ·hashtable(哈希表):当哈希类型无法满足ziplist的条件时,Redis会使用hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降,而hashtable的读写时间复杂度为O(1)。

3.使用场景

        用户信息

        文章详情

列表

1.常用命令

【Redis—基础】基本数据结构与应用_第4张图片

2.内部编码

        3.2版本之前列表类型的内部编码有两种:

       ·ziplist(压缩列表):当列表的元素个数小于list-max-ziplist-entries配置(默认512个),同时列表中每个元素的值都小于list-max-ziplist-value配置时(默认64字节),Redis会选用ziplist来作为列表的内部实现来减少内存的使用。

       ·linkedlist(链表):当列表类型无法满足ziplist的条件时,Redis会使用linkedlist作为列表的内部实现。

       3.2版本开始列表的内部编码均改为quicklist

3.使用场景

        消息队列

        文章列表

集合

1.常用命令

【Redis—基础】基本数据结构与应用_第5张图片

2.内部编码

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

       ·intset(整数集合):当集合中的元素都是整数且元素个数小于set-max-intset-entries配置(默认512个)时,Redis会选用intset来作为集合的内部实现,从而减少内存的使用。

       ·hashtable(哈希表):当集合类型无法满足intset的条件时,Redis会使用hashtable作为集合的内部实现。

3.使用场景

        标签

        生成随机数、抽奖

        社交需求

有序集合

1.常用命令

【Redis—基础】基本数据结构与应用_第6张图片

zpopmax/bzpopmax、zpopmin/bzpopmin(5.0)

2.内部编码

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

        ·ziplist(压缩列表):当有序集合的元素个数小于zset-max-ziplist-entries配置(默认128个),同时每个元素的值都小于zset-max-ziplist-value配置(默认64字节)时,Redis会用ziplist来作为有序集合的内部实现,ziplist可以有效减少内存的使用。

        ·skiplist(跳跃表):当ziplist条件不满足时,有序集合会使用skiplist作为内部实现,因为此时ziplist的读写效率会下降。

3.使用场景

        排行榜

你可能感兴趣的:(redis)