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。缓存
字符串类型的内部编码有3种:网络
·int:8个字节的长整型。session
·embstr:小于等于39个字节的字符串。数据结构
·raw:大于39个字节的字符串。多线程
Redis会根据当前值的类型和长度决定使用哪一种内部编码实现。架构
缓存并发
计数
共享session、分布式锁
限速
哈希类型的内部编码有两种:
·ziplist(压缩列表):当哈希类型元素个数小于hash-max-ziplist-entries配置(默认512个)、同时全部值都小于hash-max-ziplist-value配置(默认64字节)时,Redis会使用ziplist做为哈希的内部实现,ziplist使用更加紧凑的结构实现多个元素的连续存储,因此在节省内存方面比hashtable更加优秀。
·hashtable(哈希表):当哈希类型没法知足ziplist的条件时,Redis会使用hashtable做为哈希的内部实现,由于此时ziplist的读写效率会降低,而hashtable的读写时间复杂度为O(1)。
用户信息
文章详情
3.2版本以前列表类型的内部编码有两种:
·ziplist(压缩列表):当列表的元素个数小于list-max-ziplist-entries配置(默认512个),同时列表中每一个元素的值都小于list-max-ziplist-value配置时(默认64字节),Redis会选用ziplist来做为列表的内部实现来减小内存的使用。
·linkedlist(链表):当列表类型没法知足ziplist的条件时,Redis会使用linkedlist做为列表的内部实现。
3.2版本开始列表的内部编码均改成quicklist。
消息队列
文章列表
集合类型的内部编码有两种:
·intset(整数集合):当集合中的元素都是整数且元素个数小于set-max-intset-entries配置(默认512个)时,Redis会选用intset来做为集合的内部实现,从而减小内存的使用。
·hashtable(哈希表):当集合类型没法知足intset的条件时,Redis会使用hashtable做为集合的内部实现。
标签
生成随机数、抽奖
社交需求
zpopmax/bzpopmax、zpopmin/bzpopmin(5.0)
有序集合类型的内部编码有两种:
·ziplist(压缩列表):当有序集合的元素个数小于zset-max-ziplist-entries配置(默认128个),同时每一个元素的值都小于zset-max-ziplist-value配置(默认64字节)时,Redis会用ziplist来做为有序集合的内部实现,ziplist能够有效减小内存的使用。
·skiplist(跳跃表):当ziplist条件不知足时,有序集合会使用skiplist做为内部实现,由于此时ziplist的读写效率会降低。
排行榜