redis 开发与运维 学习心得1

时间:2021-06-14 16:25:33

主要是命令相关

第一章 初识Redis

1.redis是基于键值对的NoSQL.

 

2.redis的值可以是 string, hash, list, set, zset, bitmaps, hyperloglog, geo

 

3.redis的值不仅可以是字符串还可以是具体的数据结构

 

4.redis的2种持久方案:rdb和aof.

 

5.redis-server XXX.conf可以以conf的配置启动redis.

 

6.redis-cli shutdown可以关闭redis. 不要使用kill -9 杀死redis进程,可能会造成AOF和复制丢失数据的问题.

 

第二章 API的理解和使用

2.1预备

 1.keys * 可以列出所有键, dbsize返回所有键的总数.dbsize时间复杂度是o(1),keys是o(n).所以键太多的时候不要使用keys *

另外实验发现keys 后面*代表任意数量的字符 ?代表单个字符

 

2.exists查看键是否存在,del删除键,del后面可以跟任意数量的键,比如del a b c .....

 

3. expire可以设置键过期时间(秒),剩余时间可以使用ttl查看.

127.0.0.1:6379> expire abcd  -99 //设置负数,直接过期
(integer) 1
127.0.0.1:6379> ttl abcd
(integer) -2 // ttl 大于0表示剩余秒, -1表示键没设置过期时间, -2表示键不存在

4.type key可以查看key的数据结构

127.0.0.1:6379> set a 1
OK
127.0.0.1:6379> LPUSH b 1 2 3 4 5
(integer) 5
127.0.0.1:6379> type a
string
127.0.0.1:6379> type b
list

127.0.0.1:6379> type rrr //不存在的key
none

 

5.type命令返回的是redis对外的数据结构.每种数据结构对内还有N种内部编码实现.1种内部实现也可以对应N个外部数据结构.

使用object encoding查看内部数据编码

127.0.0.1:6379> set a 1
OK
127.0.0.1:6379> set b 2
OK
127.0.0.1:6379> lpush c 1 2 3 4
(integer) 4
127.0.0.1:6379> OBJECT encoding a
"int"
127.0.0.1:6379> OBJECT encoding b
"int"
127.0.0.1:6379> OBJECT encoding c
"ziplist"
127.0.0.1:6379> set d qqq
OK
127.0.0.1:6379> OBJECT encoding d
"embstr"
127.0.0.1:6379> set e 99999999999999
OK
127.0.0.1:6379> OBJECT encoding e
"int"
127.0.0.1:6379> set f 9999999999999999999999999.9999999999999999999999
OK
127.0.0.1:6379> OBJECT encoding f
"raw"
127.0.0.1:6379> set g 123.456
OK
127.0.0.1:6379> OBJECT encoding g
"embstr"
127.0.0.1:6379> set h 99999999999999999999999999999999999999999999999
OK
127.0.0.1:6379> OBJECT encoding h
"raw"

我觉得对于我们外部其他语言使用redis来说可能不太关心内部实现而是关心接口返回的外部数据结构..这个有点像java里通过接口引用具体的集合对象..

 

6.每次客户端调用都经历了发送命令,执行命令,返回结果三个过程.每条命令从客户端到达服务端以后不会被立刻执行,所有命令都回进入1个队列中,然后逐个被执行.

 

2.2字符串

1.字符串值不能超过512M

2.实验

127.0.0.1:6379> set k1 abc //set设置值
OK
127.0.0.1:6379> set k2 def ex 999 //ex设置过期秒数,px设置毫秒数
OK
127.0.0.1:6379> ttl k2
(integer)
997
127.0.0.1:6379> set k1 change xx // xx key 存在才更新不然不操作,用于更新
OK
127.0.0.1:6379> get k1
"change"
127.0.0.1:6379> set k1 qqq
OK
127.0.0.1:6379> get k1
"qqq"
127.0.0.1:6379> ttl k2
(integer)
957
127.0.0.1:6379> set k3 ttt nx // nx key 不存在才操作,用于插入
OK
127.0.0.1:6379> get k3
"ttt"
127.0.0.1:6379> set k3 www xx
OK
127.0.0.1:6379> get k3
"www"
127.0.0.1:6379> set k3 ppp nx // 不存在key,用nx操作.
(nil)
127.0.0.1:6379> get k3
"www"

3.setex和setnx的实验

setex key seconds value

setnx key value

setex多了1个seconds不知道为啥

127.0.0.1:6379> exists k1
(integer)
1
127.0.0.1:6379> setnx k1 change //setnx不像set nx返回nil而是返回了操作了0个key
(integer)
0
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> exists k2
(integer)
0
127.0.0.1:6379> setnx k2 v2 // 操作成功返回操作了1个key的数量
(integer)
1
127.0.0.1:6379> setnx k2 v22
(integer)
0
127.0.0.1:6379>

127.0.0.1:6379> exists k1
(integer) 1
127.0.0.1:6379> setex k1 999 v999
OK
127.0.0.1:6379> ttl k1
(integer) 996
127.0.0.1:6379>

setnx可以作为分布式锁的一种方案.因为redis是单线程只有1个操作会成功返回1,其他都是0

 

4.mset和mget批量操作

127.0.0.1:6379> mset k1 v1 k2 v2 k3 v4
OK
127.0.0.1:6379> mget k1 k2 k3 k4
1) "v1"
2) "v2"
3) "v4"
4) (nil)
127.0.0.1:6379>

 

5.计数

incr incrby自增,decr decrby自减

127.0.0.1:6379> set k1 NaN
OK
127.0.0.1:6379> INCR k1 //不是数字自增报错
(error) ERR value is not an integer or out of range
127.0.0.1:6379> set k2 1
OK
127.0.0.1:6379> incr k2
(integer) 2
127.0.0.1:6379> incr k2
(integer) 3
127.0.0.1:6379> get k2
"3"
127.0.0.1:6379> incrby k2 3
(integer) 6
127.0.0.1:6379> incrby k2 NaN //同incr
(error) ERR value is not an integer or out of range
127.0.0.1:6379> incrby k2 -3 // 自增指定数量可以自增负数
(integer) 3
127.0.0.1:6379> decr k1
(error) ERR value is not an integer or out of range
127.0.0.1:6379> decr k2 1
(error) ERR wrong number of arguments for 'decr' command
127.0.0.1:6379> decr k2
(integer) 2
127.0.0.1:6379> decrby k2 2
(integer) 0
127.0.0.1:6379> decrby k2 -9 //同自增
(integer) 9
127.0.0.1:6379> exists k3
(integer) 1
127.0.0.1:6379> del k3
(integer) 1
127.0.0.1:6379> exists k3
(integer) 0
127.0.0.1:6379> incr k3 //操作不存在的key,值直接当成0
(integer) 1
127.0.0.1:6379> del k3
(integer) 1
127.0.0.1:6379> incr k3 3
(error) ERR wrong number of arguments for 'incr' command
127.0.0.1:6379> incrby k3 3 //同incr
(integer) 3
127.0.0.1:6379>
127.0.0.1:6379> del k1
(integer) 1
127.0.0.1:6379> del k1
(integer) 0
127.0.0.1:6379> set k1 0.1
OK
127.0.0.1:6379> incr k1 //自增自减只能用于整数
(error) ERR value is not an integer or out of range
127.0.0.1:6379>

 

6.append追加字符串

127.0.0.1:6379> exists k1
(integer) 1
127.0.0.1:6379> del k1
(integer) 1
127.0.0.1:6379> set k1 hello
OK
127.0.0.1:6379> APPEND k1 " world" //返回字符串长度
(integer) 11
127.0.0.1:6379> get k1
"hello world"
127.0.0.1:6379>
127.0.0.1:6379> get k1
"hello world"
127.0.0.1:6379> APPEND k1 "'''"
(integer) 14
127.0.0.1:6379> APPEND k1 """"
Invalid argument(s)
127.0.0.1:6379> APPEND k1 "\"\"" //追加"可以用/"
(integer) 16
127.0.0.1:6379> get k1
"hello world'''\"\""
127.0.0.1:6379> set k1 ""
OK
127.0.0.1:6379> get k1
""
127.0.0.1:6379> append k1 ""
(integer) 0
127.0.0.1:6379> append k1 "
Invalid argument(s)
127.0.0.1:6379> append k1 ''
(integer) 0
127.0.0.1:6379> append k1 '"' //或者用'"'
(integer) 1
127.0.0.1:6379> get k1
"\""
127.0.0.1:6379> append k1 "'"
(integer) 2
127.0.0.1:6379> get k1
"\"'"
127.0.0.1:6379>

 

7.用strlen返回字符串长度,用getset可以设置新值并且返回原本字符串的值(有可能是nil).setrange key offset value可以改变指定位置字符,从0开始计数返回字符串长度

getrange key start end返回substr. 0开始计数,start和end都包括

127.0.0.1:6379> set k1 helloworld
OK
127.0.0.1:6379> GETRANGE k1 1 2
"el"
127.0.0.1:6379>

127.0.0.1:6379> GETRANGE k1 2 -1 // -1是最后1个字符串
"lloworld"
127.0.0.1:6379> GETRANGE k1 2 -2
"lloworl"
127.0.0.1:6379> GETRANGE k1 2 0
""
127.0.0.1:6379> GETRANGE k1 2 -0
""
127.0.0.1:6379>

 

8.字符串内部有3种编码,int 8字节长整型,embstr<=39字节的字符串,raw>39字节的字符串

 

127.0.0.1:6379> set k1 9203372036054477800
OK
127.0.0.1:6379> OBJECT encoding k1
"int"
127.0.0.1:6379> set k1 9233372000000000000
OK
127.0.0.1:6379> OBJECT encoding k1
"embstr"

8字节是64位,java里long的范围应该是

-9233372036854477808-9233372036854477808 (https://zhidao.baidu.com/question/256678932.html)

但是不知道为什么这里redis似乎不是

127.0.0.1:6379> set k1 呵 //length=3
OK
127.0.0.1:6379> object encoind k1
(error) ERR Syntax error. Try OBJECT (refcount|encoding|idletime)
127.0.0.1:6379> object encoding k1
"embstr"
127.0.0.1:6379> strlen k1
(integer) 3
127.0.0.1:6379> set k1 呵呵呵呵呵呵呵呵呵呵呵呵呵 //length=39
OK
127.0.0.1:6379> object encoding k1
"embstr"
127.0.0.1:6379> set k1 呵呵呵呵呵呵呵呵呵呵呵呵呵a //40
OK
127.0.0.1:6379> strlenth k1
(error) ERR unknown command 'strlenth'
127.0.0.1:6379> strlen k1
(integer) 40
127.0.0.1:6379> object encoding k1
"raw"
127.0.0.1:6379>

似乎是1个中文UTF-8占3个字节的缘故

 

2.3哈希

1.

hset key field value 

het key field

127.0.0.1:6379> hset k1 f1 v1
(integer) 1
127.0.0.1:6379> hget k1
(error) ERR wrong number of arguments for 'hget' command
127.0.0.1:6379> hget k1 f1
"v1"
127.0.0.1:6379> HGETALL k1
1) "f1"
2) "v1"
127.0.0.1:6379>

 

2.hdel key field [...field]

127.0.0.1:6379> hset k1 f1 v1
(integer) 1
127.0.0.1:6379> hset k1 f2 v2
(integer) 1
127.0.0.1:6379> hset k1 f3 v3
(integer) 1
127.0.0.1:6379> hdel k1 f1 f2 //返回删除个数
(integer) 2
127.0.0.1:6379> hget k1
(error) ERR wrong number of arguments for 'hget' command
127.0.0.1:6379> hgetall k1
1) "f3"
2) "v3"
127.0.0.1:6379>

 

3.hlen key返回field的个数

 

4.hmget field [field....]

hmset key field value [field value...]

批量操作hash

127.0.0.1:6379> hmset k1 f1 v1 f2 v2 f3 v3
OK
127.0.0.1:6379> mhget k1 f1 f2 f3
(error) ERR unknown command 'mhget'
127.0.0.1:6379> hmget k1 f1 f2 f3
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> HGETALL k1
1) "f1"
2) "v1"
3) "f2"
4) "v2"
5) "f3"
6) "v3"
127.0.0.1:6379>

 

5.

hexists key field 判断field是否存在

127.0.0.1:6379> HEXISTS l1 f1
(integer) 0
127.0.0.1:6379> HEXISTS k1 f1
(integer) 1
127.0.0.1:6379> hget k1 f1
"v1"
127.0.0.1:6379> hget l1 f1
(nil)
127.0.0.1:6379>

 

6.

hkeys * 获取所有field

hvals获取所有value

hgetall key 获取所有fieldvalue

127.0.0.1:6379> HKEYS k1
1) "f1"
2) "f2"
3) "f3"
127.0.0.1:6379> HVALS k1
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> HGETALL k1
1) "f1"
2) "v1"
3) "f2"
4) "v2"
5) "f3"
6) "v3"
127.0.0.1:6379>

 

7.

没有hincr命令.hincrby和hincrbyfloat和hstrlen与String的类似

8.

hash的内部编码有ziplist(个数小于512,或者所有值小于64字节),hashtable

 

2.4列表

一个列表最多可以存储2^32 -1 个元素.

 

lpush key value [value...]

rpush key value[value...]

127.0.0.1:6379> exists k1
(integer) 1
127.0.0.1:6379> del k1
(integer) 1
127.0.0.1:6379> lpush a b c
(error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> lpush k1 a b c
(integer) 3
127.0.0.1:6379> rpush k1 d e f
(integer) 6
127.0.0.1:6379> lrange k1 0 -1
1) "c"
2) "b"
3) "a"
4) "d"
5) "e"
6) "f"
127.0.0.1:6379> lrange k1 2 3 //取下标对应的元素,从0开始
1) "a"
2) "d"
127.0.0.1:6379>

 

linsert key before|after pivotValue value 在pivotValue之前或者之后插入元素

127.0.0.1:6379> lrange k1 0 -1
1) "c"
2) "b"
3) "a"
4) "d"
5) "e"
6) "f"
127.0.0.1:6379>
127.0.0.1:6379> LINSERT k1 before a 9
(integer) 7
127.0.0.1:6379> lrange k1 0 -1
1) "c"
2) "b"
3) "9"
4) "a"
5) "d"
6) "e"
7) "f"
127.0.0.1:6379> LINSERT k1 after a 8
(integer) 8
127.0.0.1:6379> lrange k1 0 -1
1) "c"
2) "b"
3) "9"
4) "a"
5) "8"
6) "d"
7) "e"
8) "f"
127.0.0.1:6379> lpush k1 a
(integer) 9
127.0.0.1:6379> lrange k1 0 -1
1) "a"
2) "c"
3) "b"
4) "9"
5) "a"
6) "8"
7) "d"
8) "e"
9) "f"
127.0.0.1:6379> LINSERT k1 after a 7 //在找到的第一个元素后面添加然后直接return
(integer) 10
127.0.0.1:6379> lrange k1 0 -1
1) "a"
2) "7"
3) "c"
4) "b"
5) "9"
6) "a"
7) "8"
8) "d"
9) "e"
10) "f"
127.0.0.1:6379> rINSERT k1 after a 7 //没有rinsert
(error) ERR unknown command 'rINSERT'
127.0.0.1:6379>

 

lindex key index 获取指定位置的元素,负数就是从最后面1个元素开始数

127.0.0.1:6379> lrange k1 0 -1
1) "a"
2) "7"
3) "c"
4) "b"
5) "9"
6) "a"
7) "8"
8) "d"
9) "e"
10) "f"
127.0.0.1:6379> lindex k1 1
"7"
127.0.0.1:6379> lindex k1 -2 //倒数第二个元素
"e"
127.0.0.1:6379>

 

llen key获取列表元素个数

 

lpop key和rpop key用于删除元素

 

lrem key count value找到value以后最多删除count个值为value的元素

count>0才能够左往右删除,<0从右往左,=0全部删除

127.0.0.1:6379> lrange k1 0 -1
1) "a"
2) "7"
3) "c"
4) "b"
5) "9"
6) "a"
7) "8"
8) "d"
9) "e"
10) "f"
127.0.0.1:6379> lrem k1 2 a //2个a都删除了
(integer) 2
127.0.0.1:6379> lrange k1 0 -1
1) "7"
2) "c"
3) "b"
4) "9"
5) "8"
6) "d"
7) "e"
8) "f"
127.0.0.1:6379> lrem k1 8 -1
(integer) 0
127.0.0.1:6379> lrem k1 -1 8 //删除1个8右边开始
(integer) 1
127.0.0.1:6379> lrange k1 0 -1
1) "7"
2) "c"
3) "b"
4) "9"
5) "d"
6) "e"
7) "f"
127.0.0.1:6379> lrem k1 0 e //所有e都删除
(integer) 1
127.0.0.1:6379> lrange k1 0 -1
1) "7"
2) "c"
3) "b"
4) "9"
5) "d"
6) "f"
127.0.0.1:6379>

 

ltrim key start end 按照索引保留元素

127.0.0.1:6379> exists k1
(integer) 1
127.0.0.1:6379> lrange k1 0 -1
1) "7"
2) "c"
3) "b"
4) "9"
5) "d"
6) "f"
127.0.0.1:6379> LTRIM k1 1 3
OK
127.0.0.1:6379> lrange k1 0 -1
1) "c"
2) "b"
3) "9"
127.0.0.1:6379>

 

lset key index newValue可以修改index的元素

127.0.0.1:6379> lrange k1 0 -1
1) "c"
2) "b"
3) "9"
127.0.0.1:6379> lset k1 0 a
OK
127.0.0.1:6379> lrange k1 0 -1
1) "a"
2) "b"
3) "9"
127.0.0.1:6379> lset k1 99 a
(error) ERR index out of range
127.0.0.1:6379>

 

blpop key [key...] timeout 弹出key最左边的元素,阻塞timeout秒.

brpop同理

127.0.0.1:6379> lrange k1 0 -1
1) "a"
2) "b"
3) "9"
127.0.0.1:6379> blpop k1 9
1) "k1"
2) "a"
127.0.0.1:6379> exists k2
(integer) 1
127.0.0.1:6379> del k2
(integer) 1
127.0.0.1:6379> del k2
(integer) 0
127.0.0.1:6379> blpop k2 9
(nil)
(9.02s)
127.0.0.1:6379>

多个key只要有1个能返回就立即返回.

多个客户端同时阻塞,添加元素后.哪个客户端命令先执行哪个就先返回,剩下的继续阻塞.

 

列表的内部实现有ziplist和linkedlist.条件范围同hash

 

使用场景:

lpush和brpop可以实现消息队列.

 

2.5集合

集合不允许重复yuansu,zuiduo储存2^32-1个元素.

 

sadd key element [element...] 新增元素

srem key element [element...] 删除元素

scard key 计算元素个数(竟然不是slen...)

smenbers key 返回集合所有元素

127.0.0.1:6379> exists k3
(integer) 1
127.0.0.1:6379> type k3
string
127.0.0.1:6379> get k3
"3vv\n"
127.0.0.1:6379> del k3
(integer) 1
127.0.0.1:6379> sadd k3 e1 e2 e3 e4
(integer) 4
127.0.0.1:6379> srem e2 e5
(integer) 0
127.0.0.1:6379> srem k3 e2 e5 //e2存在 e5不存在
(integer) 1 //成功删除e2返回结果1
127.0.0.1:6379> scard k3 //返回集合元素个数为3
(integer) 3
127.0.0.1:6379> SMEMBERS k3 //查看所有元素
1) "e1"
2) "e4"
3) "e3"
127.0.0.1:6379>

 

sismenmber key element 判断元素是否在集合内

srandmember key [count] 随机返回count个元素,默认为1

spop 随机弹出1个元素

127.0.0.1:6379> smembers k3
1) "e1"
2) "e4"
3) "e3"
127.0.0.1:6379> sismember k3 e1 //存在元素返回1
(integer) 1
127.0.0.1:6379> sismember k3 e2 //不存在返回0
(integer) 0
127.0.0.1:6379> sismember k3 e1 e2
(error) ERR wrong number of arguments for 'sismember' command
127.0.0.1:6379> sranmember key 1
(error) ERR unknown command 'sranmember'
127.0.0.1:6379> sranmember k3 1
(error) ERR unknown command 'sranmember'
127.0.0.1:6379> srandmember k3 1 //随机返回1个元素不删除
1) "e4"
127.0.0.1:6379> srandmember k3 1
1) "e1"
127.0.0.1:6379> srandmember k3 4
1) "e1"
2) "e4"
3) "e3"
127.0.0.1:6379> spop k3 //随机返回1个元素并删除
"e1"
127.0.0.1:6379> smembers
(error) ERR wrong number of arguments for 'smembers' command
127.0.0.1:6379> smembers k3
1) "e4"
2) "e3"
127.0.0.1:6379> spop k3 9 //3.2以后支持
(error) ERR wrong number of arguments for 'spop' command
127.0.0.1:6379>

 

sinter key [key...] 取交集

sunion key [key...] 取并集

sdiff key [key..] 取差集

sinterstore destination key [keys...]

union和diff同理

127.0.0.1:6379> del k1 k2 k3
(integer) 3
127.0.0.1:6379> sadd k1 1 2 3 4 5 6 7
(integer) 7
127.0.0.1:6379> sadd k2 3 4 5 6
(integer) 4
127.0.0.1:6379> sadd k3 5 6 7 8 9 10
(integer) 6
127.0.0.1:6379> sinter k1 k2
1) "3"
2) "4"
3) "5"
4) "6"
127.0.0.1:6379> sinter k1 k2 k3
1) "5"
2) "6"
127.0.0.1:6379> sinterstore k4 k1 k2 k3
(integer) 2
127.0.0.1:6379> sdiff k1 k2
1) "1"
2) "2"
3) "7"
127.0.0.1:6379> sdiff k1 k2 k3
1) "1"
2) "2"
127.0.0.1:6379> SDIFFSTORE k6 k1 k2 k3
(integer) 2
127.0.0.1:6379>

 

集合内部使用intset或者hashtable实现

intset为集合所有元素都为整形或者元素小于等于512个时候

hashtable为不满足intset的时候 

 

场景

可以用于用户标签

 

2.6有序集合

 有序集合保留了集合不能有重复元素的特征,但是可以排序,每个元素都有个对应的分数作为排序依据(分数可以重复).

 

 zadd key score member [score member...] 添加元素

zcard key 计算元素个数

zscore key member 计算元素的分数

127.0.0.1:6379> del k1
(integer) 1
127.0.0.1:6379> zadd k1 1 e1 2 e2 3 e3 4 e4 5 e5
(integer) 5
127.0.0.1:6379> zcard k1
(integer) 5
127.0.0.1:6379> zscore k1 e3
"3"
127.0.0.1:6379>

 

zrank key member [member...] 和 zrevrank key member 对元素进行排序输出排序好吗,从0开始

zrem key remember [member...] 对元素进行删除

zincrby key incrememt member 增加成员的分数

127.0.0.1:6379> zrem k1 e2
(integer) 1
127.0.0.1:6379> zrank k1 e1
(integer) 0
127.0.0.1:6379> zrevrank k1 e1
(integer) 3
127.0.0.1:6379> ZINCRBY k1 99 e1
"100"
127.0.0.1:6379> zrevrank k1 e1
(integer) 0
127.0.0.1:6379> zrank k1 e1
(integer) 3
127.0.0.1:6379>

 

zrange key start end [withscores] 低到高排序输出start-end的元素

zrevrange key start end [withscores] 高到低排序输出元素

127.0.0.1:6379> zrange k1 0 -1 // 输出所有元素 -1是最后1个 0是第一个
1) "e3"
2) "e4"
3) "e5"
4) "e1"
127.0.0.1:6379> zrange k1 0 0
1) "e3"
127.0.0.1:6379> zrange k1 0 -3
1) "e3"
2) "e4"
127.0.0.1:6379> zrange k1 1 1
1) "e4"
127.0.0.1:6379> zrange k1 0 -1 withscores
1) "e3"
2) "3"
3) "e4"
4) "4"
5) "e5"
6) "5"
7) "e1"
8) "100"
127.0.0.1:6379> zrevrange k1 0 -1 withscores
1) "e1"
2) "100"
3) "e5"
4) "5"
5) "e4"
6) "4"
7) "e3"
8) "3"
127.0.0.1:6379>

 

zrangebyscore key min max [withscores] [limit offset count]

zrevrangebyscore key max min [withscores] [limit offser count]

返回指定分数范围内的成员

127.0.0.1:6379> zrange k1  0 -1 withscores
1) "e3"
2) "3"
3) "e4"
4) "4"
5) "e5"
6) "5"
7) "e1"
8) "100"
127.0.0.1:6379>
127.0.0.1:6379> zrangebyscore k1 0 999 withscores
1) "e3"
2) "3"
3) "e4"
4) "4"
5) "e5"
6) "5"
7) "e1"
8) "100"
127.0.0.1:6379> zrangebyscore k1 0 +inf withscores //+inf表示无限大
1) "e3"
2) "3"
3) "e4"
4) "4"
5) "e5"
6) "5"
7) "e1"
8) "100"
127.0.0.1:6379> zrangebyscore k1 (3 +inf withscores //默认是[闭区间 (表示开区间
1) "e4"
2) "4"
3) "e5"
4) "5"
5) "e1"
6) "100"
127.0.0.1:6379> zrangebyscore k1 {3 +inf withscores
(error) ERR min or max is not a float
127.0.0.1:6379> zrangebyscore k1 [3 +inf withscores //似乎不能是[
(error) ERR min or max is not a float
127.0.0.1:6379> zrangebyscore k1 3 -inf withscores
(empty list or set)
127.0.0.1:6379> zrangebyscore k1 3 2 withscores
(empty list or set)
127.0.0.1:6379> ZREVRANGEBYSCORE k1 +inf 0 withscores //reverse的时候先写max再写min
1) "e1"
2) "100"
3) "e5"
4) "5"
5) "e4"
6) "4"
7) "e3"
8) "3"
127.0.0.1:6379> ZREVRANGEBYSCORE k1 (100 0 withscores
1) "e5"
2) "5"
3) "e4"
4) "4"
5) "e3"
6) "3"
127.0.0.1:6379> ZREVRANGEBYSCORE k1 (100 101 withscores
(empty list or set)
127.0.0.1:6379>

 

zcount key min max 返回分数范围内成员个数

zremrangebyzrank key start end 删除元素,按升序

zremrangebyscore key min max 删除元素按分数

127.0.0.1:6379> zcount k1 50 +inf
(integer) 1
127.0.0.1:6379> ZRANK k1 0 -1
(error) ERR wrong number of arguments for 'zrank' command
127.0.0.1:6379> zrange k1 0 -1
1) "e3"
2) "e4"
3) "e5"
4) "e1"
127.0.0.1:6379> zrange k1 0 -1 withscores
1) "e3"
2) "3"
3) "e4"
4) "4"
5) "e5"
6) "5"
7) "e1"
8) "100"
127.0.0.1:6379> ZREMRANGEBYRANK k1 0 1
(integer) 2
127.0.0.1:6379> zrange k1 0 -1 withscores
1) "e5"
2) "5"
3) "e1"
4) "100"
127.0.0.1:6379> ZREMRANGEBYSCORE k1 0 5
(integer) 1
127.0.0.1:6379> zrange k1 0 -1 withscores
1) "e1"
2) "100"
127.0.0.1:6379>

 

zinterstore destnation numkeys key [key...] [weights weight [weight....]] [aggragate sum|min|max] 计算交集

127.0.0.1:6379> del k1
(integer) 1
127.0.0.1:6379> ZADD k1 10 e1 20 e2 30 e3 40 e4 50 e5
(integer) 5
127.0.0.1:6379> del k2
(integer) 1
127.0.0.1:6379> ZADD k2 11 e1 22 e2 33 e3 44 e4 55 e5
(integer) 5
127.0.0.1:6379> zadd k2 66 e6
(integer) 1
127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2
(integer) 5
127.0.0.1:6379> zrange k1_2 0 -1
1) "e1"
2) "e2"
3) "e3"
4) "e4"
5) "e5"
127.0.0.1:6379> zrange k1_2 0 -1 withscores
1) "e1"
2) "21"
3) "e2"
4) "42"
5) "e3"
6) "63"
7) "e4"
8) "84"
9) "e5"
10) "105"
127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 weights 0.5 1
(integer) 5
127.0.0.1:6379> zrange k1_2 0 -1 withscores //默认是weight都是1,aggregate是sum
1) "e1"
2) "16"
3) "e2"
4) "32"
5) "e3"
6) "48"
7) "e4"
8) "64"
9) "e5"
10) "80"
127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 weights 0.3 //weights写了1个就必须都得写完
(error) ERR syntax error
127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 weights 0.3 1
(integer) 5
127.0.0.1:6379> zrange k1_2 0 -1 withscores
1) "e1"
2) "14"
3) "e2"
4) "28"
5) "e3"
6) "42"
7) "e4"
8) "56"
9) "e5"
10) "70"
127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 weights 0.5 0.5
(integer) 5
127.0.0.1:6379> zrange k1_2 0 -1 withscores
1) "e1"
2) "10.5"
3) "e2"
4) "21"
5) "e3"
6) "31.5"
7) "e4"
8) "42"
9) "e5"
10) "52.5"
127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 weights 1 1 aggragate min
(error) ERR syntax error
127.0.0.1:6379> ZINTERSTORE k1_2 2 k1 k2 weights 1 1 aggregate min
(integer) 5
127.0.0.1:6379> zrange k1_2 0 -1 withscores
1) "e1"
2) "10"
3) "e2"
4) "20"
5) "e3"
6) "30"
7) "e4"
8) "40"
9) "e5"
10) "50"
127.0.0.1:6379>

 

zunionstore destination numkeys key [key...] [weights weight [weight...]] [aggregate sum|min|max] 计算并集

127.0.0.1:6379> clear
127.0.0.1:6379> zrange k1 0 -1 withscores
1) "e1"
2) "10"
3) "e2"
4) "20"
5) "e3"
6) "30"
7) "e4"
8) "40"
9) "e5"
10) "50"
127.0.0.1:6379> zrange k2 0 -1 withscores
1) "e1"
2) "11"
3) "e2"
4) "22"
5) "e3"
6) "33"
7) "e4"
8) "44"
9) "e5"
10) "55"
11) "e6"
12) "66"
127.0.0.1:6379> zunoin k1_2 2 k1 k2 weights 1 0.5
(error) ERR unknown command 'zunoin'
127.0.0.1:6379> zunion k1_2 2 k1 k2 weights 1 0.5
(error) ERR unknown command 'zunion'
127.0.0.1:6379> zunionstore k1_2 2 k1 k2 weights 1 0.5
(integer) 6
127.0.0.1:6379> zrange k1_2 0 -1 WITHSCORES
1) "e1"
2) "15.5"
3) "e2"
4) "31"
5) "e6"
6) "33"    
7) "e3" //e6只有33因为k1里没有,k2 weight是0.5
8) "46.5"
9) "e4"
10) "62"
11) "e5"
12) "77.5"
127.0.0.1:6379>

 

内部使用ziplist和skiplist.

元素个数小于128并且只都小于64字节时用ziplist否则用skiplist

场景

主要用于排行榜

 

2.7键管理

rename key newKey 重命名键

renamenx key newKey  当newkey不存在的时候才会成功重命名

randomkey 随机返回1个键

127.0.0.1:6379> del k1 k2
(integer) 2
127.0.0.1:6379> mset k1 haha k2 hehe
OK
127.0.0.1:6379> mget k1 k2
1) "haha"
2) "hehe"
127.0.0.1:6379> rename k1 k2
OK
127.0.0.1:6379> exists k1
(integer) 0
127.0.0.1:6379> exists k2
(integer) 1
127.0.0.1:6379> get k2
"haha"
127.0.0.1:6379> rename k2 k2 //一样的key在3.2以下版本会boom
(error) ERR source and destination objects are the same
127.0.0.1:6379> keys *
1) "e"
2) "k2"
3) "b"
4) "k4"
5) "f"
6) "h"
7) "k6"
8) "k3"
9) "d"
10) "g"
11) "k1_2"
12) "c"
13) "a"
127.0.0.1:6379> RANDOMKEY
"k4"
127.0.0.1:6379> RANDOMKEY
"k4"
127.0.0.1:6379> RANDOMKEY
"a"
127.0.0.1:6379> RANDOMKEY
"k4"
127.0.0.1:6379> RANDOMKEY
"b"
127.0.0.1:6379>

 

expire key seconds 设置X秒后键过期,负数直接删除

expireat key timestamp 在秒级时间戳后x后过期

ttl key 返回键的剩余过期秒数

persist 清除键过期时间

127.0.0.1:6379> exists k2
(integer) 1
127.0.0.1:6379> ttl k2
(integer) -1 // -1不过期
127.0.0.1:6379> expire k2 999
(integer) 1
127.0.0.1:6379> ttl k2
(integer) 997
127.0.0.1:6379> PERSIST k2 //永不过期
(integer) 1
127.0.0.1:6379> ttl k2
(integer) -1
127.0.0.1:6379> get k2
"haha"
127.0.0.1:6379> del k2
(integer) 1
127.0.0.1:6379> ttl k2
(integer) -2 // -2键不存在
127.0.0.1:6379>

 

pexpire key milliseconds 设置键X毫秒后捡国旗

pexpireat key milliseconds-timestamp 在毫秒级时间戳X后键过期

 

set会去除过期时间

127.0.0.1:6379> set k1 heihei ex 999
OK
127.0.0.1:6379> get k1
"heihei"
127.0.0.1:6379> ttl k1
(integer) 994
127.0.0.1:6379> ttl k1
(integer) 993
127.0.0.1:6379> set k1 wahaha
OK
127.0.0.1:6379> ttl k1
(integer) -1 // 时间被清除了
127.0.0.1:6379>

 

redis不支持对二级数据结构做过期时间设置

setex命令是原子执行的

 

move可以在redis内部数据库进行键迁移

127.0.0.1:6379> select 0
OK
127.0.0.1:6379> get k1
"wahaha"
127.0.0.1:6379> move k1 1
(integer) 1
127.0.0.1:6379> exists k1
(integer) 0
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> keys *
1) "k1"
127.0.0.1:6379[1]> get k1
"wahaha"
127.0.0.1:6379[1]>

 

dump key 将值序列化

restore key ttl value 将值反序列化到数据库中

127.0.0.1:6379> exists k1
(integer) 1
127.0.0.1:6379> type k1
string
127.0.0.1:6379> dump l1
(nil)
127.0.0.1:6379> dump k1
"\x00\x06wahaha\x06\x00\xd7\x03\xb2\xb3I5\xd9\xc7"
127.0.0.1:6379>
127.0.0.1:6380> RESTORE k1 0 "\x00\x06wahaha\x06\x00\xd7\x03\xb2\xb3I5\xd9\xc7"
OK
127.0.0.1:6380> get k1
"wahaha"
127.0.0.1:6380>

 

migrate host port key| "" destination-db timeout [copy] [replace] [keys key [key ...]] 在redis之前迁移数据,migrate命令具有原子性

127.0.0.1:6379> keys *
1) "e"
2) "b"
3) "k4"
4) "k1"
5) "f"
6) "h"
7) "k6"
8) "k3"
9) "d"
10) "g"
11) "k1_2"
12) "c"
13) "a"
127.0.0.1:6379> MIGRATE localhost 6379 0 0 copy replace e b k4 k1 f h k6 k3 d g k1_2 c a
(error) ERR syntax error
127.0.0.1:6379> MIGRATE localhost 6380 0 0 copy replace e b k4 k1 f h k6 k3 d g k1_2 c a
(error) ERR syntax error
127.0.0.1:6379> MIGRATE localhost 6380 0 1000 copy replace e b k4 k1 f h k6 k3 d g k1_2 c a
(error) ERR syntax error
127.0.0.1:6379> MIGRATE 127.0.0.1 6380 0 0 copy replace e b k4 k1 f h k6 k3 d g k1_2 c a
(error) ERR syntax error
127.0.0.1:6379> MIGRATE localhost 6380 0 0 copy replace keys e b k4 k1 f h k6 k3 d g k1_2 c a
(error) ERR When using MIGRATE KEYS option, the key argument must be set to the empty string
127.0.0.1:6379> MIGRATE localhost 6380 "" 0 0 copy replace keys e b k4 k1 f h k6 k3 d g k1_2 c a //不要忘记写""
OK
127.0.0.1:6379>
127.0.0.1:6380> keys *
1) "k1_change"
127.0.0.1:6380> del k1_change
(integer) 1
127.0.0.1:6380> keys *
(empty list or set) //等待6379迁移数据过来
127.0.0.1:6380> keys *
1) "k4"
2) "c"
3) "b"
4) "k3"
5) "e"
6) "a"
7) "k6"
8) "k1_2"
9) "h"
10) "d"
11) "k1"
12) "f"
13) "g"
127.0.0.1:6380>

不知道为什么我1个redis实例不同数据库之间迁移不行,我觉得可能是因为这是1个事务,同个实例要接受迁移的键也要等这个事务结束才行.所以迁移需要等待接受好才能结束,接受需要等迁移事务结束才可以开始造成的.(猜测)

127.0.0.1:6379> MIGRATE localhost 6379 "" 1 0 copy replace keys e b k4 k1 f h k6 k3 d g k1_2 c a
(error) IOERR error or timeout reading to target instance
(1.00s)
127.0.0.1:6379> MIGRATE localhost 6379 "" 1 3000 copy replace keys e b k4 k1 f h k6 k3 d g k1_2 c a
(error) IOERR error or timeout reading to target instance
(3.00s)
127.0.0.1:6379>

 

 

迁移命令比较

命令 作用域 原子性 支持多个键
move redis实例内部
dump+restore redis实例之间
migrate redis实例之间