Redis基础
Redis安装
官网下载最新稳定版本的压缩包,解压缩后放到任意目录下,进行解压后的目录执行:
make (编译代码)
make install (安装)
安装后执行redis-cli-v
查看Redis版本号
Redis启动
最好复制一个配置文件放到一个文件夹下,并在配置文件中修改daemonize yes
,表示开启守护线程,启动时指定配置文件
redis-server (–configKey1 configValue1 –configKey2 configValue2)
redis-server 配置文件所在地址
没指定则使用默认配置
Redis命令行客户端
- 连接redis
不使用h表示使用默认ip和默认端口redis-cli -h {host} -p {port} ({command})
- 关闭redis
redis-cli shutdown (nosave|save) 是否生成持久化文件
Redis常用命令
- 查看所有键
keys *
- 键总数
dbsize
- keys和dbsize的区别:
dbsize直接获取redis内置的键总数,时间复杂度是O(1),keys命令遍历所有键,时间复杂度是O(n),线上禁止使用
- 检查键是否存在
exists key
- 删除键
del key1,key2,…
- 设置键过期时间
expire key seconds
- 返回键剩余时间
没有设置时间返回-1,没有这个键返回-2ttl keys
- 键的数据类型
type key
数据结构和内部编码
redis有一下几种数据结构类型:string
,hash
,list
,set
(集合),zset
(有序集合),每种数据结构都有自己的内部编码,可以通过一下命令查看内部编码
object encoding key
单线程架构
从客户端发送到redis的所有命令不会被立即立即执行,会被放在一个队列中,然后逐个执行,所以客户端命令的执行顺序是不确定的。
基本数据结构
字符串
是redis最基础的数据结构,包括字符串,数字,二进制(最大不超过512Mb)
常用命令
- 设置值
set key value [ex seconds] [px milliseconds] [nx|xx]
setnx 相当于set加上nx,表示当键不存在时才能插入,用于插入数据
setex 相当于set加上ex
xx表示键已经存在,用于更新
mset key value key value … 批量插入多个键值对 - 获取值
get key
mget key key … 批量获取多个值
批量操作能够将藕提高开发效率,减少多次网络请求的时间,一次性发出,一次性接收
- 计数
对值做自增操作,如果值不是整数则报错,如果原来的键不存在,则会自动创建并按0自增为1incr key
此外还提供了decr(自减),incrby(自增指定数值),decrby(自减指定数字),incrbyfloat(自增浮点数)
- 其他
append key value 在字符串末尾追加
strlen key 获取字符串长度,中文占用3个字节
getset key value 设置并返回原来的值
setrange key offset value 设定指定位置的字符
getrange key start end 获取部分字符串
内部编码
- int:8个字节的长整型
- embstr:小于等于39个字节的字符串
- raw:大于39个字节的字符串
使用场景
- 缓存功能
- 计数
- 共享session
- 限速
哈希
哈希类型指键值本身又是一个键值对的结构,其形式如下图:
常用命令
hset key field value 还有hsetnx,作用域是filed
hget key field
hdel key field [field …] 删除一个或者多个field,返回删除个数
hlen key 计算field个数
hmget key field [field …]
hmset key field [key field …]
hexists key field 判断field是否存在
hkeys key 获取所有field
hvals key 获取所有value
hgetall key 获取所有的field-value
hincrby key field
hincrbyfloat key field 作用域都是field
hstrelen key field
如果哈希元素比较多,会存在Redis阻塞的可能,尽量使用hmget
内部编码
- ziplist(压缩列表)
当哈希类型元素个数小于hash-max-ziplist-entries
配置(默认512字节),同时所有值小于hash-max-ziplist-value
配置(默认64)时,使用ziplist作为内部实现,ziplist使用更加紧凑的结构实现多个元素的连续存储,在节省内存方面更加优秀 - hashtable(哈希表)
当哈希类型无法满足ziplist的条件时,使用hashtable作为内部实现,因为此时ziplist读写效率会下降,而hashtable读写时间复杂度为O(1)
使用场景
将关系型数据库每一行数据存储为一个哈希键
列表
列表(list)用来存储多个有序的字符串,列表总每个字符串称为元素(element),一个列表最多可以存储2^32-1个元素,可以充当栈和队列
常用命令
添加
rpush key value [value…] 在右边依次插入元素
lpush key value [value…] 在左边依次插入元素
linsert key before|after pivot value 向某个元素的前或后插入元素查找
索引下标从左到右是0到N-1,但从右到左是 -1到-N,lrange key start end 指定范围内的元素列表,end包含了自身(0到-1表示查询所有)
lindex key index 获取列表指定索引下标的元素
llen key 获取列表长度删除
lpop key 从左侧弹出删除元素
rpop key 从右侧删除
lrem key count value 删除指定元素
ltrim key start end 按照索引范围截取列表
lrem命令会从列表中找到等于value的元素进行删除:
- count>0 从左到右,删除最多count个元素
- count<0 从右到左,删除count的绝对值个元素
- count=0 删除所有
修改
lset key index newValue
阻塞操作
参数key为多个列表的键,timeout为阻塞时间
blpop key [key …] timeout
brpop key [key …] timeout
- 列表为空
如果timeout不等于0,则等待相应秒数后返回,如果timeout=0,那么客户端一直阻塞下去,此时如果另一个客户端添加了数据element1,客户端立即返回 - 列表不为空
客户端会立即返回,如果有多个键,只会弹出第一个键并返回
注意事项
如果多个客户端对同一个键执行brpop,当列表只有一个元素时,最先执行的客户端可以获取到弹出的值,其他的会继续阻塞
内部编码
- ziplist(压缩列表)
当哈希类型元素个数小于list-max-ziplist-entries
配置(默认512),同时所有值小于list-max-ziplist-value
配置(默认64)时,使用ziplist作为内部实现,ziplist使用更加紧凑的结构实现多个元素的连续存储,在节省内存方面更加优秀 - linkedlist(链表)
当哈希类型无法满足ziplist的条件时,使用linkedlist作为内部实现。
使用场景
- 栈,队列
- 消息队列(抢购)
- 文章列表
集合
集合(set)可以保存多个字符串元素,但是不允许有重复元素,并且集合中的元素是无序的,一个集合最多可以存储2^32-1个元素,集合可以进行内部的增删改查和多个集合取交集,并集,差集
基本命令
- 集合内操作
添加元素
sadd key element [element …]
删除元素 Redis内部变量
srem key element [element …]
计算元素个数,空间复杂度为O(1),直接使用redis中的变量
scard key
判断给定元素是否在集合中
sismenber key element
随机从集合中返回指定个数的元素
srandmember key [count]
从集合中随机弹出元素
spop key
获取所有元素
smembers key
- 集合间操作
求多个集合的交集
sinter key [key …]
求多个集合的并集
sunion key [key …]
求多个集合的差集
sdiff key [key …]
将交集、并集、差集的结果保存到指定的key中
sinterstore destiantion key [key …]
sunionstore destination key [key …]
sdiffstore destination key [key …]
内部编码
- intset(整数集合)
当集合中的元素都是整数而且与元素个数小于set-max-intset-entries
配置(默认512个)时,使用该编码减少内存的使用 - hashtable(哈希表)
其他条件下使用哈希表作为内部实现
使用场景
- 标签
- 生成随机数(抽奖)
- 社交需求
有序集合
有序集合(zset)保留集合元素不能重复的特性,但是有序集合中的元素可以排序,它为每一个元素设定一个score作为排序的依据
常用命令
- 集合内
添加成员,时间复杂度为O(log(n))
zadd key score member [score member …]
参数
- nx member必须不存在
- xx member必须存在
- ch 返回此次操作后,有序集合元素和分数发生变化的个数
- incr 对score做增加
计算成员个数
zcard key
计算某个成员的分数
zscore key member
计算成员排名,从0开始算
zrank key member 从低到高
zrevrank key member 从高到低
删除成员
zrem key member [member …]
增加指定分数
zincrby key increment member
返回指定排名范围的成员
zrange key start end [withscores]
zrverange key start end [withscores]
返回指定分数范围的成员,limit可以限制输出的起始位置位置和个数,同时min和max还支持开区间(小括号)和闭区间(中括号),-inf表示负无穷,+inf表示正无穷
zrangebyscore key min max [withscores] [limit offset count]
zrverangebyscore key max min [withscores] [limit offset count]
返回指定分数范围的成员个数
zcount key min max
删除指定排名内的升序元素
zremrangebyrank key start end
删除指定分数范围的成员
zremrangebyscore key min max
- 集合间的操作
交集
zinterstore destination numkeys key [key …] [
weights
weight [weight …]] [aggregate
sum|min|,max]
- destination:交集结果保存在这个键
- numkeys:需要做交集计算键的个数
- key[key…]:需要做交集计算的键
- weights:每个键的权重,做交集运算时会将自身分数乘上权重,默认是1
- aggregate sum|max|min:计算交集后的分值可以是和、最大值、最小值,默认是sum
并集
zunionstore destination numkeys key [key …] [weights weight [weight …]][aggregate sum|min|max]
内部编码
- ziplist(压缩列表)
当哈希类型元素个数小于zset-max-ziplist-entries
配置(默认128个),同时所有值小于zset-max-ziplist-value
配置(默认64)时,使用ziplist作为内部实现,ziplist使用更加紧凑的结构实现多个元素的连续存储,在节省内存方面更加优秀 - skiplist(跳跃表)
当ziplist条件不满足时,有序集合会使用skiplist作为内部实现,因为此时ziplist的读写效率会下降
使用场景
- 排行榜系统
- 用户点赞
键管理
单个键管理
键重名:如果在rename之前该键已经存在,则其值也会被覆盖掉,可以使用renamenx
, 确保只有当newKey不存在时才能执行。
由于重命名期间会执行del命令删除旧的键,如果键对应的值比较大,会存在阻塞Redis的可能性
rename key newkey
随机返回一个键
randomkey
键过期
键在seconds秒之后过期
expire key seconds
键在秒级时间戳timestamp后过期
expireat key timestamp
设置毫秒级过期时间
pexpire key milliseconds 在milliseconds毫秒后过期
pexpireat key milliseconds-timestamp 在毫秒级时间戳后过期
- 无论使用过期时间是秒还是时间戳,秒级还是毫秒级,redis内部最终使用pexpireat
查看剩余过期时间,-1
表示没有设置过期时间,-2
表示键不存在,大于等于0的整数表示剩余时间
ttl keys
pttl keys 精度更高,达到毫秒级
使用键过期的注意事项:
- 如果expire key的键不存在,返回结果为0
- 如果过期时间设置为负值,键会立即被删除,相当于del
persist
可以将键的过期时间清除- 对于字符串类型键,执行set命令会去掉过期时间
- redis不支持二级数据结构(例如哈希,列表)内部元素的过期功能
- setex命令作为set+expire的组合,是原子执行,同时减少一次网络通讯的时间
迁移键
redis中可以有多个数据库,彼此相互隔离,将指定的键从当前数据库迁移到目标数据库
move key db
在不同redis之间执行数据迁移,该操作不具备原子性,需要在两个客户端进行操作
dump key 返回value
restore key ttl value value为上面的值
该过程分为两步:
- 在源redis上,dump命令将键值序列化,格式采用RDB格式
- 在目标redis上,restore命令将上面序列化的值复原,ttl参数代表过期时间,等于0代表没有过期时间
migrate
命令也用于在不同redis之间迁移,它将move、dump、restore进行整合,具有原子性,只需要在一个客户端就可以执行完成,同时支持多个键进行迁移
migrate host port key|”” destination-db timeout [copy] [replace] [keys key [key]]
- host:目标redis的ip地址
- port:目标redis的端口
- key|””:迁移一个键为key,多个键为空字符串“”
- destination-db:目标Redis数据库索引,例如0号数据库,就写0
- timeout:迁移的超时时间,单位为毫秒
- copy:如果添加此选项,迁移后不删除源键
- replace:如果添加此选项,migrate不管目标redis是否存在该键都会进行迁移并进行数据覆盖
- keys key …: 迁移的多个键
遍历键
全量遍历键
keys pattern
pattern使用glob风格的通配符:
- *代表匹配任意字符
- 任意一个字符代表匹配一个字符
- ?代表匹配一个字符
- []代表匹配部分字符,[1,3]代表匹配1,3,[1-10]代表匹配1到10的任意数字
- \ x 用来做转移,例如问号,星号等
如果Redis包含了大量的键,使用keys可能会造成阻塞
渐进式遍历
scan cursor [match pattern] [count number]
scan采用渐进式遍历,要扫描所有需要多次执行,可以一定程度上避免阻塞
参数说明:
- cursor:游标,第一次从0开始,每次执行完scan会返回下一次的游标,直到返回0表示遍历结束
- match pattern:遍历匹配
- count nnumber 每次遍历的键个数,默认10
对于hgetall,smembers,zrange可能产生的阻塞问题,对应的命令分别为hscan
,sscan
,zscan
在执行scan的过程中,如果有键发生变化(增加、删除、修改),可能会产生新增的键没有遍历到,遍历出重复的键等问题
数据库管理
一个Redis中可以有多个数据库实例,使用数字索引区分,默认配置有16个数据库
切换数据库
select daIndex
清除数据库
清除当前数据库
flushdb
清除所有数据库
flushall