- 查看全部 key
node02:6379> keys *
1) "name"
2) "age"
3) "sex"
- 查看當(dāng)前數(shù)據(jù)庫中的 key 的總數(shù)
node02:6379> dbsize
(integer) 3
dbsize命令在計(jì)算鍵總數(shù)時(shí)不會(huì)遍歷所有鍵,而是直接獲取Redis內(nèi)置的鍵總數(shù)變量,所以dbsize命令的時(shí)間復(fù)雜度是O(1)。
而keys命令會(huì)遍歷所有鍵,所以它的時(shí)間復(fù)雜度是O(n),當(dāng)Redis保存了大量鍵時(shí),應(yīng)該謹(jǐn)慎使用。
- 檢查 key 是否存在
# 1 代表存在
node02:6379> exists name
(integer) 1
# 0 代表不存在
node02:6379> exists id
(integer) 0
- 刪除 key
# 返回值是成功刪除鍵的個(gè)數(shù)
node02:6379> del name
(integer) 1
# 可以同時(shí)刪除多個(gè)鍵
node02:6379> del age sex
(integer) 2
# 刪除一個(gè)不存在的鍵將會(huì)返回 0
node02:6379> del xxx
(integer) 0
- 設(shè)置 key 過期時(shí)間,查看 key 剩余存活時(shí)間
node02:6379> set name1 tom
OK
# 設(shè)置過期時(shí)間,單位 s
node02:6379> expire name1 60
(integer) 1
# 查看 key 剩余存活時(shí)間,返回 >= 0 的數(shù),代表剩余存活時(shí)間
node02:6379> ttl name1
(integer) 53
node02:6379> ttl name1
(integer) 0
# 返回 -2 代表 key 過期,已經(jīng)被刪除
node02:6379> ttl name1
(integer) -2
node02:6379> exists name1
(integer) 0
node02:6379> set name2 tony
OK
# 返回 -1 代表 key 未設(shè)置過期時(shí)間
node02:6379> ttl name2
(integer) -1
# expireat命令可以設(shè)置鍵在哪個(gè)時(shí)間過期,時(shí)間用時(shí)間戳表示
# pttl可以查看key的毫秒級(jí)別的剩余存活時(shí)間
127.0.0.1:6379> expireat name 1606798800000
(integer) 1
127.0.0.1:6379> pttl name
(integer) 1605192006672745
127.0.0.1:6379> pttl name
(integer) 1605192006668840
127.0.0.1:6379> pttl name
(integer) 1605192006667824
# pexpire:設(shè)置毫秒級(jí)的過期時(shí)間
127.0.0.1:6379> pexpire age 600000
(integer) 1
127.0.0.1:6379> ttl age
(integer) 595
# pexpireat:鍵在毫秒級(jí)時(shí)間戳timestamp后過期
127.0.0.1:6379> pexpireat sex 1606798800000
(integer) 1
127.0.0.1:6379> pttl sex
(integer) 5147367
127.0.0.1:6379> ttl sex
(integer) 5143
127.0.0.1:6379> expire sex -2
# 如果是給一個(gè)鍵設(shè)置過期時(shí)間為負(fù)數(shù),會(huì)立即刪除這個(gè)鍵
(integer) 1
127.0.0.1:6379> exists sex
(integer) 0
# 清除key的過期時(shí)間
127.0.0.1:6379> persist name
(integer) 1
127.0.0.1:6379> ttl name
(integer) -1
# 使用set命令覆蓋一個(gè)字符串,則會(huì)清空過期時(shí)間
127.0.0.1:6379> set name tom
OK
127.0.0.1:6379> expire name 100
(integer) 1
127.0.0.1:6379> ttl name
(integer) 98
127.0.0.1:6379> set name tony
OK
127.0.0.1:6379> ttl name
(integer) -1
# setex:set+expire的組合,創(chuàng)建key并設(shè)置過期時(shí)間
# setex:不但是原子執(zhí)行,同時(shí)減少了一次網(wǎng)絡(luò)通訊的時(shí)間
127.0.0.1:6379> setex name 10 tom
OK
127.0.0.1:6379> ttl name
(integer) 8
Redis不支持二級(jí)數(shù)據(jù)結(jié)構(gòu)(例如哈希、列表)內(nèi)部元素的過期功能,例如不能對(duì)列表類型的一個(gè)元素做過期時(shí)間設(shè)置
- 查看 key 的數(shù)據(jù)結(jié)構(gòu)類型
node02:6379> type name2
string
# 如果 key 不存在,返回 none
node02:6379> type name1
none
- 查看某個(gè)命令的幫助文檔
node02:6379> help set
SET key value [EX seconds] [PX milliseconds] [NX|XX]
summary: Set the string value of a key
since: 1.0.0
group: string
- 鍵重命名
# 將鍵的名稱由name改成first_name
127.0.0.1:6379> rename name first_name
OK
127.0.0.1:6379> get first_name
"tom"
# 重命名時(shí),如果新名稱的key已經(jīng)存在,就會(huì)覆蓋掉
127.0.0.1:6379> set name "tom"
OK
127.0.0.1:6379> set first_name "bob"
OK
127.0.0.1:6379> rename name first_name
OK
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> get first_name
"tom"
# renamenx:當(dāng)新名稱的key不存在時(shí)才進(jìn)行重命名
127.0.0.1:6379> set name tom
OK
127.0.0.1:6379> set first_name bob
OK
# 返回0代表沒有完成重命名
127.0.0.1:6379> renamenx name first_name
(integer) 0
# 如果新key和舊key的名稱相同,在3.2版本之前會(huì)報(bào)錯(cuò),3.2版本之后返回OK
127.0.0.1:6379> rename name name
OK
由于重命名鍵期間會(huì)執(zhí)行del命令刪除舊的鍵,如果鍵對(duì)應(yīng)的值比較大,會(huì)存在阻塞Redis的可能性
- 隨機(jī)返回一個(gè)鍵
127.0.0.1:6379> randomkey
"name"
- 遷移鍵
move:內(nèi)部遷移鍵,Redis內(nèi)部可以有多個(gè)數(shù)據(jù)庫,彼此在數(shù)據(jù)上是相互隔離的,move key db就是把指定的鍵從源數(shù)據(jù)庫移動(dòng)到目標(biāo)數(shù)據(jù)庫中
dump+restore:在不同的Redis實(shí)例之間進(jìn)行數(shù)據(jù)遷移
在源Redis上,dump命令會(huì)將鍵值序列化,格式采用的是RDB格式
在目標(biāo)Redis上,restore命令將上面序列化的值進(jìn)行復(fù)原,其中ttl參數(shù)代表過期時(shí)間,如果ttl=0代表沒有過期時(shí)間
# 源redis將某個(gè)key序列化
127.0.0.1:6379> dump age
"\x00\xc0\x12\t\x00\x9d+/\x83A\xa7'\x9a"
# 目標(biāo)redis反序列化,這里是用一個(gè)Redis實(shí)例模擬的
127.0.0.1:6379> del age
(integer) 1
127.0.0.1:6379> restore age 0 "\x00\xc0\x12\t\x00\x9d+/\x83A\xa7'\x9a"
OK
127.0.0.1:6379> get age
"18"
migrate:用于在Redis實(shí)例間進(jìn)行數(shù)據(jù)遷移,migrate命令就是將dump、restore、del三個(gè)命令進(jìn)行組合,migrate命令具有原子性,而且從Redis3.0.6版本以后已經(jīng)支持遷移多個(gè)鍵的功能,有效地提高了遷移效率。migrate遷移key的流程如下:

# 如果目標(biāo)redis中不存在此key,則返回OK
127.0.0.1:6379> migrate localhost 6380 age 0 1000
OK
127.0.0.1:6380> get age
"18"
# 如果目標(biāo)redis中已經(jīng)存在此key,則需添加replace選項(xiàng)進(jìn)行覆蓋,否則會(huì)報(bào)錯(cuò)
127.0.0.1:6379> set age 30
OK
127.0.0.1:6379> migrate localhost 6380 age 0 1000 replace
OK
127.0.0.1:6380> get age
"30"
127.0.0.1:6379> set age 20
OK
127.0.0.1:6379> migrate localhost 6380 age 0 1000
(error) ERR Target instance replied with error: BUSYKEY Target key name already exists.
# 默認(rèn)情況下,源redis的key遷移到目標(biāo)redis后就會(huì)刪除
# 如果想保留redis的key,即進(jìn)行復(fù)制操作,那么需要加copy選項(xiàng)
127.0.0.1:6379> migrate localhost 6380 age 0 1000 copy replace
OK
# 如果源redis的key不存在,會(huì)接收到"NOKEY"的提示
127.0.0.1:6379> migrate localhost 6380 age 0 1000 replace
NOKEY
# 遷移多個(gè)key,首先把單個(gè)key位置設(shè)置為空字符串,然后在命令最后添加多個(gè)key
127.0.0.1:6379> migrate localhost 6380 "" 0 1000 copy replace keys name age sex
OK
127.0.0.1:6380> get name
"tony"
127.0.0.1:6380> get age
"20"
127.0.0.1:6380> get sex
"1"
- 遍歷鍵
# keys命令支持通配符
127.0.0.1:6379> keys [j,r]edis
1) "redis"
2) "jedis"
127.0.0.1:6379> keys h*
1) "hill"
2) "hello"
# 刪除所有以"app"開頭的key,可以在shell中使用以下命令:
redis-cli keys app* | xargs redis-cli del
如果Redis包含了大量的鍵,執(zhí)行keys命令很可能會(huì)造成Redis阻塞,所以一般建議不要在生產(chǎn)環(huán)境下使用keys命令,keys命令可以在以下2種情況下使用:
- 在一個(gè)不對(duì)外提供服務(wù)的Redis從節(jié)點(diǎn)上執(zhí)行,這樣不會(huì)阻塞到客戶端的請(qǐng)求,但是會(huì)影響到主從復(fù)制
- 如果確認(rèn)鍵值總數(shù)比較少,可以執(zhí)行該命令
使用scan命令漸進(jìn)式的遍歷所有鍵,可以有效防止阻塞
# scan cursor [match pattern] [count number]
# cursor是必需參數(shù),實(shí)際上cursor是一個(gè)游標(biāo),第一次遍歷從0開始
# 每次scan遍歷完都會(huì)返回當(dāng)前游標(biāo)的值,直到游標(biāo)值為0,表示遍歷結(jié)束
# match pattern是可選參數(shù),它的作用的是做模式的匹配
# count number是可選參數(shù),它的作用是表明每次要遍歷的鍵個(gè)數(shù),默認(rèn)值是10,此參數(shù)可以適當(dāng)增大
127.0.0.1:6379> 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
# 第一次遍歷,游標(biāo)為0,
# 返回值第一部分代表下次遍歷的游標(biāo)
# 返回值第二部分代表本次遍歷得到的key
127.0.0.1:6379> scan 0
1) "14"
2) 1) "a"
2) "b"
3) "y"
4) "v"
5) "x"
6) "u"
7) "t"
8) "w"
9) "h"
10) "o"
127.0.0.1:6379> scan 14
1) "11"
2) 1) "c"
2) "s"
3) "j"
4) "q"
5) "f"
6) "p"
7) "z"
8) "i"
9) "e"
10) "r"
11) "m"
# 游標(biāo)返回0,代表所有key遍歷完畢
127.0.0.1:6379> scan 11
1) "0"
2) 1) "n"
2) "k"
3) "g"
4) "l"
5) "d"
除了scan以外,Redis提供了面向哈希類型、集合類型、有序集合的掃描遍歷命令,解決諸如hgetall、smembers、zrange可能產(chǎn)生的阻塞問題,對(duì)應(yīng)的命令分別是hscan、sscan、zscan,它們的用法和scan基本類似。
漸進(jìn)式遍歷可以有效的解決keys命令可能產(chǎn)生的阻塞問題,但是scan并非完美無瑕,如果在scan的過程中如果有鍵的變化(增加、刪除、修改),那么遍歷效果可能會(huì)碰到如下問題:新增的鍵可能沒有遍歷到,遍歷出了重復(fù)的鍵等情況,也就是說scan并不能保證完整的遍歷出來所有的鍵,這些是我們?cè)陂_發(fā)時(shí)需要考慮的。
- 數(shù)據(jù)庫管理
Redis用數(shù)字作為多個(gè)數(shù)據(jù)庫的實(shí)現(xiàn),Redis默認(rèn)配置中是有16個(gè)數(shù)據(jù)庫,編號(hào)從0-15,默認(rèn)使用0號(hào)數(shù)據(jù)庫
# 1. 切換數(shù)據(jù)庫
127.0.0.1:6379> get a
"a"
# select dbIndex 可以切換數(shù)據(jù)庫
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> get a
(nil)
Redis在3.0之后已經(jīng)開始逐漸弱化這個(gè)功能,例如Redis的分布式實(shí)現(xiàn)Redis Cluster只允許使用0號(hào)數(shù)據(jù)庫,只不過為了向下兼容老版本的數(shù)據(jù)庫功能,該功能沒有完全廢棄掉,那么為什么要廢棄掉這個(gè)功能呢?
- Redis是單線程的。如果使用多個(gè)數(shù)據(jù)庫,那么這些數(shù)據(jù)庫仍然是使用一個(gè)CPU,彼此之間還是會(huì)受到影響的
- 多數(shù)據(jù)庫的使用方式,會(huì)讓調(diào)試和運(yùn)維不同業(yè)務(wù)的數(shù)據(jù)庫變的困難,假如有一個(gè)慢查詢存在,依然會(huì)影響其他數(shù)據(jù)庫,這樣會(huì)使得別的業(yè)務(wù)方定位問題非常的困難
- 部分Redis的客戶端根本就不支持這種方式。即使支持,在開發(fā)的時(shí)候來回切換數(shù)字形式的數(shù)據(jù)庫,很容易弄亂
建議如果要使用多個(gè)數(shù)據(jù)庫功能,完全可以在一臺(tái)機(jī)器上部署多個(gè)Redis實(shí)例,彼此用端口來做區(qū)分,因?yàn)楝F(xiàn)代計(jì)算機(jī)或者服務(wù)器通常是有多個(gè)CPU的。這樣既保證了業(yè)務(wù)之間不會(huì)受到影響,又合理地使用了CPU資源。
# 2. 清空數(shù)據(jù)庫
flushdb # 清空當(dāng)前數(shù)據(jù)庫的數(shù)據(jù)
flushall # 清空所有數(shù)據(jù)庫的數(shù)據(jù)
127.0.0.1:6379[1]> set name tom
OK
127.0.0.1:6379[1]> select 2
OK
127.0.0.1:6379[2]> set name tony
OK
127.0.0.1:6379[2]> select 3
OK
127.0.0.1:6379[3]> set name bob
OK
# 使用flushdb清空3號(hào)數(shù)據(jù)庫的數(shù)據(jù),其他數(shù)據(jù)庫的數(shù)據(jù)還在
127.0.0.1:6379[3]> flushdb
OK
127.0.0.1:6379[3]> get name
(nil)
127.0.0.1:6379[3]> select 2
OK
127.0.0.1:6379[2]> get name
"tony"
# 使用flushdb清空數(shù)據(jù),則其他數(shù)據(jù)庫的數(shù)據(jù)也被清除了
127.0.0.1:6379[2]> flushall
OK
127.0.0.1:6379[2]> keys *
(empty list or set)
127.0.0.1:6379[2]> select 1
OK
127.0.0.1:6379[1]> keys *
(empty list or set)
127.0.0.1:6379[1]> select 3
OK
127.0.0.1:6379[3]> keys *
(empty list or set)
flushdb/flushall命令可以非常方便的清理數(shù)據(jù),但是也帶來兩個(gè)問題:
- 這兩個(gè)命令會(huì)將所有數(shù)據(jù)清除,一旦誤操作后果不堪設(shè)想
- 如果當(dāng)前數(shù)據(jù)庫鍵值數(shù)量比較多,使用這兩個(gè)命令會(huì)存在阻塞Redis的可能性