一、Redis的数据结构概述
Redis本质上是一款内存存储系统,与其他任何存储系统一样,Value值在数据结构上其实都划分为对外(使用者视角)的数据结构,以及对内(服务器)的内部编码两类。
1.1 使用者视角的数据结构
包括以下五种:
- string——字符串
- hash——哈希
- list——列表
- set——集合
- zset——有序集合
这些都是Redis对外的数据结构。
1.2 服务器存储角度的内部编码
上面的每种数据结构都有自己底层的内部编码实现,而且不止一种实现。
Redis底层存在多种内部编码实现,以应对不同场景选择合适的内部编码。
这样设计,与MySQL可插拔存储引擎有异曲同工之妙。
其一,将对外的数据结构与内部编码分开,可以在不影响用户使用的同时,可以迭代改进内部编码,只要一旦有更优秀的内部编码被开发出来,可直接进行替换,而用户几乎不用感知。
其二,在不同的使用场景下,可以针对性的使用更合适的内部编码,可以借助配置参数让redis自动去适配。
二、使用场景
2.1 字符串使用场景
字符串类型的值,可以是字符串,包括简单的字符串和诸如JSON、XML等的复杂字符串,数字(整数、浮点数),甚至二进制(图片、音频、视频),但是值最大不能超过512M。
字符串类型的内部编码有以下3种:
- int:8个字节的长整型
- embstr: 小于等于39个字节的字符串
- raw:大于39个字节的字符串
Redis会根据当前值的类型和长度决定使用哪种内部编码实现。
使用场景:
- 缓存功能
这应该是Redis被使用最多的场景,也是比较典型的场景。一般用作应用和数据库两者之间的加速层,减少数据库的压力。
- 计数
常见于朋友圈点赞数、微博点赞数、视频播放网站上的视频播放数等。
- 共享session
用于集中管理web服务器的session。
- 限速
常用于用户每分钟获取手机验证码的频率,比如一分钟不能超过5次的场景。
2.2 哈希使用场景
哈希类型的内部编码有两种:
- ziplist,压缩列表
当哈希类型元素个数小于hash-max-ziplist-entries配置(默认512个)、同时所有值都小于hash-max-ziplist-value配置(默认64字节)时,Redis会使用ziplist作为哈希的内部实现,ziplist使用更加紧凑的结构实现多个元素的连续存储。
- hashtable,哈希表
当哈希类型无法满足ziplist的条件时,Redis会使用hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降,而hashtable的读写时间复杂度为O(1)。
使用场景:
用于缓存整个对象类型数据。如果一个对象的某些字段经常需要一起使用,很少分开单独使用的话,就可以将这些字段作为一个整体对象,使用哈希结构缓存。
2.3 列表使用场景
列表的内部编码实现有两种:
- ziplist,压缩列表
当列表的元素个数小于list-max-ziplist-entries配置(默认512个),同时列表中每个元素的值都小于 list-max-ziplist-value配置(默认64字节),Redis会选用ziplist来作为列表的内部实现来减少内存的使用。
- linkedlist,链表
当列表类型无法满足ziplist的条件时,Redis会使用linkedlist作为列表的内部实现。
使用场景:
- 消息队列
Redis的lpush+brpop命令组合即可实现阻塞队列,生成者客户端使用lrpush从列表左侧插入元素,多个消费者客户端使用brpop命令阻塞式的“抢”列表尾部的元素,多个客户端保证了消费的负载均衡和高可用。
- 文章列表
博客系统每个用户都有属于自己的文章列表,可借助Redis的集合类型实现分页展示文章列表的需求。因为列表是有序的,而且支持按照索引范围获取元素。
2.4 集合使用场景
集合的使用场景是标签(tag)。
2.5 有序集合使用场景
有序集合使用场景是排行榜系统。