Redis常用命令
基本全局命令
#查看所有键
keys *
#选择数据库 0-15
select 11
#清除所有数据 返回ok
flushall
#清除当前数据库数据 返回ok
flushdb
#键是否存在 存在1不存在0
exists key
#当前数据库中键的数量
dbsize
#删除键 多个 del key1 key2 key3 O(1)|O(n) n是键的个数
#成功返回删除键的数量 失败返回0
del key [key...]
#设置键过期时间 惰性删除OR定期扫描
expire key second
#键剩余时间
#>=0 键剩余时间 -1未设置过期时间 -2 键不存在
ttl key
#键的类型 键不存在返回none
type key
String
特点
Key
最大512M,Value
最大512M。
String
类型内部编码:
int
8个字节长整型,大概超过±922.32亿亿之后切换成embstr
embstr
<=39字节字符串raw
>39字节字符串
场景
缓存
播放量计数
共享session
限速:key
是IP或TEL,value
是次数,每访问一次incr
。
命令
#设置值|添加新键值 O(1)
#ex|px设置秒级|毫秒级过期时间
#nx 不存在才可设置 xx存在才可设置
set key value [ex seconds] [px millseconds] [nx|xx]
#设置过期的缩写命令 原子执行还减少了一次网络执行时间 重点
setex key seconds value
#不存在才执行成功 作为一种分布式锁的实现方案 重点
setnx key value
#获取值 O(1)
get key
#批量设置值 O(N)
mset key value [key value...]
#批量获取值 不存在的返回nil
mget key [key...]
#整数返回自增1的值 非整数返回错误 键不存在自增1返回
incr key
#自增n
incrby key increment
#自减浮点数
incrbyfloat key increment
#自减
decr key
#自减n
decrby key decrement
#在指定key后追加
append key value
#value的长度 每个中文字符占3个字节
strlen key
#设置并返回原值 键不存在返回nil
getset key value
#返回指定长度字符串
#前闭后闭 O(N) N是字符串长度 字符串较短可视为O(1)
getrange key start end
Hash
特点
Key
最大512M,Value
最大2^32-1个元素。
value
: field:value
HASH
类型内部编码:
ziplist
(压缩列表):hash
元素个数(即field
) <hash-max-ziplist-entries
(default
=512)配置且hash
元素的值<hash-max-ziplist-value
(default=64
)配置时采用。ziplist
使用更加紧凑的结构实现多个元素连续存储,节省内存。hashtable
(哈希表):不满足以上条件时采用,此时ziplist
读写效率下降。
场景
作为业务对象的缓存,如存用户信息。
对比
使用字符串存
JSON
类型的对象信息优:简化编程 劣:序列化和反序列化有开销,更新属性需要把对象反序列化再存入。
使用
hash
优:简单 劣:把控
ziplist
和hashtable
间的转换
命令
#设置值 set user:1 name k
hset key field value
#获取值 不存在返回nil
hget key field
#删除field 或多个
hdel key filed [field...]
#返回field个数 O(1)
hlen key
#批量设置
hmset key field value [field value...]
#批量获取
hmget key field [field...]
#field是否存在 有返回1 没有返回0
hexists key field
#获取所有field
hkeys key
#获取所有value
hvals key
#获取所有field-value 若f-v较多会使redis阻塞
#建议hmget需要的或使用hscan
hgetall key
#自增
hincrbyfloat key field increment
hincrby key filed increment
List
特点
Key
最大512M,Value
最大2^32-1个元素。
List
类型内部编码:quicklist
:结合了ziplist
和linkedlist
优势。
场景
消息队列
文章列表
lpush
+lpop
栈lpush
+rpop
队列lpush
+ltrim
有限集合lpush
+brpop
消息队列
命令
#从左右push
lpush
rpush
#从左右pop
lpop
rpop
#删除key中元素
#count=0 删除所有指定元素 count>0 从左到右删除count个 <从左到右删除-count个
#返回删了几个
lrem key count value
#保留指定角标间的值 start<=end 若start>end就全删除了
ltrim key start end
#在某元素前后插入新元素
#失败返回-1 成功返回现在list长度
linsert key before|after pivot value
#获取指定范围元素
#角标从左到右0~lenth-1 从右到左-1~-lenth 前闭后闭
#O(s+n) s是start的偏移量 n = end -start
lrange start end
#返回指定角标元素
#不存在返回nil 存在返回值
lindex key index
#获取list长度
len key
#设置指定角标的值
lset key index newValue
#源键弹出 目地键放入 sourceKey不存在返回nil
#sourceKey=destinationKey 即原list中的value向右移动一位
rpoplpush sourceKey destinationKey
#阻塞式操作 单位:秒
# sourceKey不存在则等待timeout
brpoplpush sourceKey destinationKey timeout
brpop key [key...] timeout
blpop key [key...] timeout
Set
特点
Key
最大512M,Value
最大2^32-1个元素。
不允许重复元素且无序。
Set
类型内部编码:
instset
:全为整数且个数小于set-max-intset-entries
(default
= 512)配置项时hashtable
:不满足上诉条件时使用
场景
标签:
给用户添加标签 sadd user1:tags tag1 tag2 tag3
给标签添加用户 sadd tag1:users user1 user2 user3
删除用户标签 srem user1:tags tag1
删除标签用户 srem tag1:users user1
添加和删除是两个事务,上述关联操作应放在事务中进行。
计算用户共同感兴趣标签:sinter user1:tags user2:tags
生成随机数:
spop
/srandmember
社交需求:
sadd
+ sinter
命令
#添加元素
sadd key element [element...]
#删除元素
srem key element [element...]
#返回元素个数 O(1) 内部维护变量
scard key
#查看指定元素是否存在于指定key中
#存在1 不存在0
sismember key element
#随机返回count个元素 O(count)
srandmember key count
#随机弹出一个元素
spop key
#获取所有元素
smembers key
#求交集 O(M*K) M键个数K集合中元素最少的个数
sinter key [key...]
#求并集 O(K) 多个集合元素个数和
sunion key [key...]
#差集 sdiff key1 key2 key3 即key1减去key2和key3中有的元素 O(K) 多个集合元素个数和
sdiff key [key...]
#求完结果并保存
sinterstore destination key [key...]
sunionstore destination key [key...]
sdiffstore destination key [key...]
Zset
特点
Key
最大512M,Value
最大2^32-1个元素。
元素不能重复,但对应的score
可以重复。
Zset
的内部编码:
ziplist
:元素个数<=zset-max-ziplist-entries
(default
= 128) && 元素长度<=zset-max-ziplist-value
(default
= 64字节)
skiplist
:不满足上述条件时
场景
排行榜
命令
#NX|XX 不存在才设置|存在才设置 O(K*log(n)) k是添加成员个数 n是当前成员个数
#ch 返回此次设置修改member的个数
#INCR socre自增 zadd zset xx ch incr 10 rank10 令rank10原来的值加10 返回加后的值
zadd key [NX|XX] [CH] [INCR] score member [score member ...]
#元素个数
zcard key
#返回该元素的分数 没有返回nil
zscore key member
#返回元素的序号 没有返回nil
#从低到高的名次 0开始 O(log(n)) n是当前有序集合成员个数
zrank key member
#从高到底的名次 0开始
zrevrank key member
#删除元素 返回删除的个数 O(k*log(n)) k删除的个数 n当前的元素总数
zrem key member [member...]
#加分 不存在的元素就会自动添加 O(log(n)) 当前元素总数
zincrby key socre member
#返回指定角标范围元素 option withscores 是否返回分数
#O(k+log(n)) k是返回的个数 n是元素总数
zrange key start end [WITHSCORES]
zrevrange key start end [WITHSCORES]
#返回指定分数范围的元素 offset指定角标 count指定返回个数
#默认闭区间 开区间左边加( -inf +inf表示负正无穷大
#O(k+log(n)) k是返回的个数 n是元素总数
zrangebyscore key min max [WITHSCORES] [LIMIT OFFSET COUNT]
zrevrangebyscore key max min [WITHSCORES] [LIMIT OFFSET COUNT]
#返回指定分数范围内成员个数 同样可指定开闭区间 O(log(n))
zcount key min max
#删除指定排名范围内元素 返回成功的个数
#O(k+log(n)) k是删除的个数 n是元素总数
zremrangebyrank key start end
#删除指定分数范围内的元素 返回成功的个数
#O(k+log(n)) k是删除的个数 n是元素总数
zremrangebyscore key min max
#交集 destination结果存储键 numkeys计算的总键数 key键 weights每个键的权重 默认1
#aggregate规定交集的分值如何汇总 默认sum
#O(n*k) + O(m*log(m)) n是成员数最小的集合的成员个数 k是集合的个数 m是结果集中成员的个数
zinterstore destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
#并集 O(n) + O(m*log(m)) n是所有集合成员个数总数 m是结果集中成员的个数
zunionstore destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
Bitmpas
特点
实际上就是字符串,只是可以对字符串进行位操作。大小限制同String
。
场景
独立用户访问计数。
setbit unique:users:20200405 166 1
即2020年4月5日这天,用户ID为166的用户访问了网站。
为避免setbit操作初始化较慢造成阻塞,用户id建议减去一定数字(比如10000)再存。
set
和bitmap
都可以存独立用户访问,需要根据实际情况评估占用空间大小。
命令
#设置值setbit key 0 0|1
setbit key offset value
#获取值 返回0|1
getbit key offset
#获取范围内为1的个数 不设置start&end 就返回所有为1的个数
bitcount key [start end]
#operation = and|or|not|xor 与或非异或
bitop operation destkey key [key ...]
#计算值中第一个值为bit的角标 start end可限制范围
bitpos key bit [start] [end]
HyperLogLog
特点
实际上就是字符串,key最大512M,不论多少数据value固定12k。
采用了基数算法,官方误差在0.81%。
笔记本尝试存100万和1000万数据后info memory
变化均约为16.1k
,应该是key
的大小和维护其他有关数据。
The HyperLogLog data structure can be used in order to count unique elements in a set using just a small constant amount of memory, specifically 12k bytes for every HyperLogLog.
p.plus a few bytes for the key itself.
The returned cardinality of the observed set is not exact, but approximated with a standard error of 0.81%.
p.s. 该数据结构的是对unique element进行计算。
test:hll:01 存100万数据
test:hll:11 存1000万数据
在我的机器上看到存100万数据误差率>0.81%。
127.0.0.1:6379[1]> keys *
1) "test:hll:11"
2) "test:hll:01"
127.0.0.1:6379[1]> pfcount test:hll:01 test:hll:11
(integer) 9972088
127.0.0.1:6379[1]> pfcount test:hll:01
(integer) 1009838
127.0.0.1:6379[1]> pfcount test:hll:11
(integer) 9972088
命令
#添加
pfadd key element [element...]
#计算一个或多个key的中不重复元素的总数
pfcount key [key...]
#多个key合并后再计算
pfmerage key [key...]
键管理
#重命名键 nx防止newKey存在 如果不加nx,重命名用了已有的键,键对应的值就丢失了。
#若旧键对应的值比较大 重名名时会删除旧键 可能阻塞Redis
rename key newKey
renamenx key newKey
#随机返回一个key
randomkey
#键过期 键不存在返回0 时间负数键立即被删除 时间戳小于现在立即被删除
#秒级时间戳后过期 pxpireat key 1469980800
exprieat key timestamp
#毫秒级过期
pexpire key millseconds
pexpireat key millseconds-timestamp
#清除键的过期时间
persist key
#set key value会清除过期时间
#键迁移到不同的数据库
move key db
--------------------------------------------------------------------------------------
#键迁移到不同数据库实例
#键被序列化 RDB格式
dump key
#在目标redis实例上恢复 ttl key过期时间,0即不过期 value 序列化值
restore key ttl value
#示例
sourceRedis:6379> dump key
"\x00\x03key\a\x00\x1ag\xe1\xfe\x95\x01\x17\x99"
targetRedis:6379> resore key 0 "\x00\x03key\a\x00\x1ag\xe1\xfe\x95\x01\x17\x99"
--------------------------------------------------------------------------------------
#用来进行数据迁移 结合了dump restore del命令,是原子操作
#host目标Redis port目标Redis端口 destination-db目标数据库号 COPY源数据不删除
#REPLACE覆盖目标Redis 若源Reids与目标Redis有相同键,但没加REPLACE会报错
#timeout迁移的超时时间
migrate host port key| destination-db timeout [COPY] [REPLACE] [KEYS key]
#示例
sourceRedis:6379> migrate 127.0.0.1 6380 "" 0 5000 keys key1 key2 key3
sourceRedis:6379> migrate 127.0.0.1 6380 key4 0 5000
#遍历键 pattern比如 * ? []各种匹配符
#键太多不建议这样使用
keys pattern
#渐进式遍历
#MATCH pattern匹配模式
#COUNT count每次遍历的个数
#hscan sscan zscan可以遍历值中的字段
#cursor知道cursor再次为0 即遍历完毕
scan cursor [MATCH pattern] [COUNT count]
#示例
127.0.0.1:6379[3]> mset a a b b c c d d e e f f g g h h i i j j k k l l m m n n o o p p q q r r s s t t u u v v w w x x y y z z
OK
127.0.0.1:6379[3]> scan 0
1) "22"
2) 1) "x"
2) "l"
3) "h"
4) "g"
5) "m"
6) "o"
7) "k"
8) "v"
9) "j"
10) "e"
127.0.0.1:6379[3]> scan 22
1) "19"
2) 1) "w"
2) "d"
3) "b"
4) "p"
5) "z"
6) "a"
7) "i"
8) "r"
9) "q"
10) "u"
127.0.0.1:6379[3]> scan 19
1) "0"
2) 1) "n"
2) "f"
3) "c"
4) "t"
5) "s"
6) "y"
TIPS
- 对有过期时间的键重新执行
set key value
会清除过期时间,见源码:
void setKey(redisDb *db, robj *key, robj *val){
if(lookUpKeyWrite(db,key) == NULL){
dbAdd(db,key,val);
}else{
dbOverWrite(db,key,val);
}
incrRefCount(val);
//清除了过期时间
removeExpire(db,key);
signalModifiedKey(db,key);
}
不建议一个Redis实例中使用多个数据库,影响性能。而应使用多个Redis实例配置多个端口。
惰性删除:
del key
不会立即删除,会放在一个独立字典维护,在下次get key
时删除,造成内存浪费。定期扫描:配置
hz
项,Redis后台每X秒进行扫描。从过期字典中随机选择20个key;
删除20key中已过期的key;
如果删除比例超过25%,重复执行。