介绍redis中数据结构及api的使用。
前言
1.数据结构与内部编码
redis主要包含5种数据结构,每种数据结构的内部编码可能有多个,redis会根据实际使用情况选择合适的编码,来优化内存与性能。
#数据结构
127.0.0.1:6379[1]> type k_string
string
#内部编码
127.0.0.1:6379[1]> OBJECT encoding k_string
"int"
数据结构与内部编码对应关系。
Tips:内部编码的限定条件,可能会根据redis的不同版本有所调整或者增加新的内部编码,这里的版本为3.0.7
。redis里中文占3个字节。
数据结构 | 内部编码 | 备注 | 优点 | 缺点 |
string | int | 8个字节的长整型 | ||
embstr | 小于等于39个字节的字符串 | |||
raw | 大于39个字节的字符串 | |||
hash | ziplist (压缩列表) |
元素个数小于hash-max-ziplist-entries配置(默认512个),同时所有值都小于hash-max-ziplist-value配置(默认64字节) | 节省内存 | 读写效率不足 |
hashtable (哈希表) |
不满足ziplist条件时 | 读写为o(1) | ||
list | ziplist (压缩列表) |
元素个数小于list-max-ziplist-entries配置(默认512个),同时所有值都小于list-max-ziplist-value配置(默认64字节) | 节省内存 | |
linkedlist (链表) |
不满足ziplist条件时 | |||
set | intset 整数集合 |
元素都是整数且元素个数小于set-maxintset-entries配置(默认512个) | 节省内存 | |
hashtable (哈希表) |
不满足intset条件时 | |||
zset | ziplist | 元素个数小于zset-max-ziplist-entries配置(默认128个),同时每个元素的值都小于zset-max-ziplist-value配置(默认64字节) | 节省内存 | |
skiplist | 不满足ziplist条件时 |
2.单线程
redis使用的是单线程与I/O多路复用模式,所有到服务器的命令都会进行排队然后逐个执行,所以需要特别注意每个命令的执行时间
,因为可能会阻塞其它命令的执行。
redis高性能因素:
- 纯内存访问,内存响应时间100纳秒左右
- 非阻塞I/O,使用epoll作为I/O多路复用技术的实现,再加上 redis自身的事件处理模型将epoll中的连接、读写、关闭都转换为事件,不 在网络I/O上浪费过多的时间
- 避免线程切换与竞态产生的消耗
字符串
字符串是最基础的数据结构,字符串的值可以是字符串(简单的字符串、复杂的字符串(例如JSON、XML))、数字(整数、浮点数),甚至是二进制(图片、音频、视频),但是值最大不能超过512MB
。
1.常用命令
命令类型 | 命令格式 | 备注 | 复杂度 | 官方说明 |
增/改 | set key value [EX seconds] [PX milliseconds] [NX|XX] | 设置键的值 | o(1) | link |
getset key value | 设置键的值,返回原值 | o(1) | link | |
mset key value [key value ...] | 设置多个键值对 | o(n) | link | |
setrange key offset value | 替换键的值 | o(1)/o(m) | link | |
append key value | 追加键的值 | o(1) | link | |
删 | del key [key ...] | 删除键,阻塞 | o(n) | link |
unlink key [key ...] | 删除键,非阻塞 | o(n) | link | |
查 | get key | 获取键的值 | o(1) | link |
mget key [key ...] | 获取多个键的值 | o(n) | link | |
其它 | incr key | 键的值加1 | o(1) | link |
incrby key increment | 键的值加给定值,整数 | o(1) | link | |
incrbyfloat key increment | 键的值加给定值,浮点数 | o(1) | link | |
decr key | 键的值减1 | o(1) | link | |
decrby key | 键的值减给定值 | o(1) | link | |
strlen key | 获取键的值长度 | o(1) | link |
2.使用场景
数据缓存
将redis作为缓存层,mysql作为存储层,可以加速读写,降低数据库的压力。
一般思路,如果缓存有读缓存,缓存没有从库里读取后返回数据,同时将数据放入缓存+过期时间,等待下次的数据访问。
计数
可用于记录商品被查看的次数、视频观看次数等,异步将统计数据同步到存储层。
session共享
目前大多数的web网站都会使用负载均衡来提高网站的可用性与并发量,如果session存储在各自服务器上的话,可能就会导致用户在A服务器存的session,当用户访问到B服务器时找不到session的情况。
可将用户的session信息存储到redis中,在redis是高可用的情况下,无论用户访问的是哪台服务器,都可以获取到session信息。
token共享
对于像微信token这种每天有获取上限的token,需要将token记录到涉及web应用都可以访问到的地方,使用redis记录是一个不错的选择。
限流
为了防止接口被恶意调用,或者对于某些接口在一定时间范围内有调用限制,可使用redis的带过期时间的数值key来处理。
哈希
哈希结构也可以叫做字典、关联数组等,键的值是(field-value)的映射关系。
1.常用命令
命令类型 | 命令格式 | 备注 | 复杂度 | 官方说明 |
增/改 | hset key field value | 设置键的field-value,单个 | o(1) | link |
hmset key field value [field value ...] | 设置键的field-value,多个 | o(n) | link | |
hsetnx key field value | 设置键的field-value,当field不存在时 | o(1) | link | |
删 | hdel key field [field ...] | 删除键的field | o(n) | link |
查 | hget key field | 获取键的field-value,单个field | o(1) | link |
hmget key field [field ...] | 获取键的field-value,多个field | o(n) | link | |
hgetall key | 获取键的field-value,所有field 此命名为重命令,控制获取元素个数 |
o(n) | link | |
hkeys key | 获取键的所有field | o(n) | link | |
hvals key | 获取键的所有field对应的value | o(n) | link | |
其它 | hexists key field | 判断键是否存在field | o(1) | link |
hincrby key field increment | 键的field对应value加给定值,整数 | o(1) | link | |
hincrbyfloat key field increment | 键的field对应value加给定值,浮点数 | o(1) | link | |
hlen key | 获取键中field数 | o(1) | link | |
hstrlen key field | 获取键的field对应value的长度 | o(1) | link | |
hscan key cursor [MATCH pattern] [COUNT count] | 递归获取键的field-value | o(1)/o(n) | link |
2.使用场景
商品/用户信息
一般商品/用户信息会有多个属性,如果只许调整某些属性值,可以比较方便。
列表
列表用来存储有序的可重复的字符串,根据使用方式可实现栈或队列的功能。
1.常用命令
命令类型 | 命令格式 | 备注 | 复杂度 | 官方说明 |
增/改 | lpush key value [value ...] | 向队列的左边插入元素 | o(n) | link |
lpushx key value | 向队列的左边插入元素,当队列不存在 | o(1) | link | |
rpush key value [value ...] | 向队列的右边插入元素 | o(n) | link | |
rpushx key value | 向队列的右边插入元素,当队列不存在 | o(1) | link | |
lset key index value | 设置队列某个位置的元素 | o(1)/o(n) | link | |
linsert key BEFORE|AFTER pivot value | 在队列某个元素的前面或后面插入元素 | o(1)/o(n) | link | |
删 | lpop key | 从队列左边弹出一个元素 | o(1) | link |
rpop key | 从队列右边弹出一个元素 | o(1) | link | |
lrem key count value | 从队列的左边或右边删除指定个数的给定元素 | o(n) | link | |
ltrim key start stop | 按索引范围裁剪队列 | o(n) | link | |
查 | lindex key index | 获取索引位置的元素 | o(n) | link |
lrange key start stop | 获取索引范围的元素 此命名为重命令,控制获取元素个数 |
o(n) | link | |
其它 | llen key | 队列中元素的个数 | o(1) | link |
2.使用场景
栈
lpush+lpop,向列表的一端插入数据,再从同样一端获取数据。
队列
lpush+rpop,向列表的一端插入数据,再从另外一端获取数据。
有限集合
lpush+ltrim,向列表的一端插入数据,获取当前列表中的记录数,当记录数超过限定值时,截断列表。
消息队列
lpush+brpop,向列表的一端插入数据,再从另外一端阻塞获取数据。
集合
集合用来存储无序的不可重复的字符串,多个集合可取交集、并 集、差集。
1.常用命令
命令类型 | 命令格式 | 备注 | 复杂度 | 官方说明 |
增/改 | sadd key member [member ...] | 向集合插入元素 | o(n) | link |
删 | srem key member [member ...] | 从集合删除元素 | o(n) | link |
spop key [count] | 从集合弹出一个元素 | o(1) | link | |
smove source destination member | 将元素从一个集合转移到另一个集合 | o(1) | link | |
查 | srandmember key [count] | 从集合中返回随机元素 | o(1)/o(n) | link |
smembers key | 从集合中返回所有元素 此命名为重命令,控制获取元素个数 |
o(n) | link | |
其它 | scard key | 集合中元素的个数 | o(1) | link |
sismember key member | 集合中是否存在某个元素 | o(1) | link | |
sscan key cursor [MATCH pattern] [COUNT count] | 递归获取集合的元素 | o(1)/o(n) | link | |
集合 | sinter key [key ...] | 获取集合的交集 | o(1) | link |
sinterstore destination key [key ...] | 获取集合的交集,并保存 | o(n*m) | link | |
sunion key [key ...] | 获取集合的并集 | o(n) | link | |
sunionstore destination key [key ...] | 获取集合的并集,并保存 | o(n) | link | |
sdiff key [key ...] | 获取集合的差集 | o(n) | link | |
sdiffstore destination key [key ...] | 获取集合的差集,并保存 | o(n) | link |
2.使用场景
用户标签
sadd,记录用户喜欢的标签,标签被哪些用户喜欢。
抽奖
sadd+spop/srandmember,从所有id中获取随机值。
社交
sadd+sinter,获取不同用户相同的标签。
有序集合
有序集合用来存储有序的不可重复的字符串,使用score来进行排序。
1.常用命令
命令类型 | 命令格式 | 备注 | 复杂度 | 官方说明 |
增/改 | zadd key [NX|XX] [CH] [INCR] score member [score member ...] | 向集合插入元素 | o(log(n)) | link |
删 | zrem key member [member ...] | 从集合删除元素 | o(m*log(n)) | link |
zremrangebyrank key start stop | 从集合删除指定排序范围的元素 | o(m*log(n)) | link | |
zremrangebyscore key min max | 从集合删除指定分数范围的元素 | o(m*log(n)) | link | |
zremrangebylex key min max | 从集合删除指定元素秩范围的元素 | o(m*log(n)) | link | |
查 | zrange key start stop [WITHSCORES] | 返回指定排序范围的元素(由低到高) | o(log(n)+m) | link |
zrangebyscore key min max [WITHSCORES] [LIMIT offset count] | 返回指定分数范围的元素(由低到高) | o(log(n)+m) | link | |
zrangebylex key min max [LIMIT offset count] | 返回指定元素秩范围的元素个数(由低到高) | o(log(n)+m) | link | |
zrevrange key start stop [WITHSCORES] | 返回指定排序范围的元素(由高到低) | o(log(n)+m) | link | |
zrevrangebyscore key max min [WITHSCORES] [LIMIT offset count] | 返回指定分数范围的元素(由高到低) | o(log(n)+m) | link | |
zrevrangebylex key max min [LIMIT offset count] | 返回指定元素秩范围的元素个数(由高到低) | o(log(n)+m) | link | |
其它 | zcard key | 集合中元素的个数 | o(1) | link |
zcount key min max | 返回指定分数范围的元素个数 | o(log(n)) | link | |
zincrby key increment member | 增加集合中元素的分值 | o(log(n)) | link | |
zlexcount key min max | 返回分数范围内的元素个数 | o(log(n)) | link | |
zrank key member | 返回元素的排名(由低到高) | o(log(n)) | link | |
zrevrank key member | 返回元素的排名(由低到高) | o(log(n)) | link | |
zscan key cursor [MATCH pattern] [COUNT count] | 递归获取集合中的元素 | o(1)/o(n) | link | |
集合 | zinterstore destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX] |
获取集合的交集 | o(n*k)+o(m*log(n)) | link |
zunionstore destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX] |
获取集合的并集 | o(n*k)+o(m*log(n)) | link |
2.使用场景
排行榜
如游戏中可以按照各种维度提供排行的功能。
键
redis中不管值是什么数据结构,它们的键一样都是字符串,对于键的管理也有相关方法。
1.常用命令
命令格式 | 备注 | 复杂度 | 官方说明 |
del key [key ...] | 删除键值对,阻塞 | o(n) | link |
unlink key arg ...options... | 删除键值对,非阻塞 | o(n) | link |
exists key [key ...] | 键是否存在 | on) | link |
expire key seconds | 设置键的过期时间,秒 | o(1) | link |
pexpire key milliseconds | 设置键的过期时间,毫秒 | o(1) | link |
expireat key timestamp | 设置键在何时过期,秒 | o(1) | link |
pexpireat key milliseconds-timestamp | 设置键在何时过期,毫秒 | o(1) | link |
persist key | 移除键的过期时间 | o(1) | link |
ttl key | 获取键的过期时间,秒 | o(1) | link |
pttl key | 获取键的过期时间,毫秒 | o(1) | link |
rename key newkey | 重命名键 | o(1) | link |
renamenx key newkey | 重命名键,newkey不存在 | o(1) | link |
type key | 键的数据结构 | o(1) | link |
object encoding [arguments [arguments ...]] | 键的内部编码 | o(1) | link |
keys pattern | 模糊匹配键,阻塞 | o(n) | link |
scan cursor [MATCH pattern] [COUNT count] | 模糊匹配键,不阻塞,渐进式 | o(1)/o(n) | link |