- 查看全部 key
node02:6379> keys *
1) "name"
2) "age"
3) "sex"
- 查看當(dāng)前數(shù)據(jù)庫(kù)中的 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 過(guò)期時(shí)間铺罢,查看 key 剩余存活時(shí)間
node02:6379> set name1 tom
OK
# 設(shè)置過(guò)期時(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 過(guò)期,已經(jīng)被刪除
node02:6379> ttl name1
(integer) -2
node02:6379> exists name1
(integer) 0
node02:6379> set name2 tony
OK
# 返回 -1 代表 key 未設(shè)置過(guò)期時(shí)間
node02:6379> ttl name2
(integer) -1
# expireat命令可以設(shè)置鍵在哪個(gè)時(shí)間過(guò)期势就,時(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í)的過(guò)期時(shí)間
127.0.0.1:6379> pexpire age 600000
(integer) 1
127.0.0.1:6379> ttl age
(integer) 595
# pexpireat:鍵在毫秒級(jí)時(shí)間戳timestamp后過(guò)期
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è)置過(guò)期時(shí)間為負(fù)數(shù)泉瞻,會(huì)立即刪除這個(gè)鍵
(integer) 1
127.0.0.1:6379> exists sex
(integer) 0
# 清除key的過(guò)期時(shí)間
127.0.0.1:6379> persist name
(integer) 1
127.0.0.1:6379> ttl name
(integer) -1
# 使用set命令覆蓋一個(gè)字符串,則會(huì)清空過(guò)期時(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è)置過(guò)期時(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)部元素的過(guò)期功能舅锄,例如不能對(duì)列表類(lèi)型的一個(gè)元素做過(guò)期時(shí)間設(shè)置
- 查看 key 的數(shù)據(jù)結(jié)構(gòu)類(lèi)型
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代表沒(méi)有完成重命名
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ù)庫(kù)老翘,彼此在數(shù)據(jù)上是相互隔離的,move key db
就是把指定的鍵從源數(shù)據(jù)庫(kù)移動(dòng)到目標(biāo)數(shù)據(jù)庫(kù)中
dump+restore:在不同的Redis實(shí)例之間進(jìn)行數(shù)據(jù)遷移
在源Redis上,dump命令會(huì)將鍵值序列化铺峭,格式采用的是RDB格式
在目標(biāo)Redis上墓怀,restore命令將上面序列化的值進(jìn)行復(fù)原,其中ttl參數(shù)代表過(guò)期時(shí)間卫键,如果ttl=0代表沒(méi)有過(guò)期時(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"開(kāi)頭的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開(kāi)始
# 每次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提供了面向哈希類(lèi)型雏婶、集合類(lèi)型物赶、有序集合的掃描遍歷命令,解決諸如hgetall
留晚、smembers
酵紫、zrange
可能產(chǎn)生的阻塞問(wèn)題,對(duì)應(yīng)的命令分別是hscan
错维、sscan
奖地、zscan
,它們的用法和scan
基本類(lèi)似需五。
漸進(jìn)式遍歷可以有效的解決keys命令可能產(chǎn)生的阻塞問(wèn)題鹉动,但是scan并非完美無(wú)瑕,如果在scan的過(guò)程中如果有鍵的變化(增加宏邮、刪除泽示、修改),那么遍歷效果可能會(huì)碰到如下問(wèn)題:新增的鍵可能沒(méi)有遍歷到蜜氨,遍歷出了重復(fù)的鍵等情況械筛,也就是說(shuō)scan并不能保證完整的遍歷出來(lái)所有的鍵,這些是我們?cè)陂_(kāi)發(fā)時(shí)需要考慮的飒炎。
- 數(shù)據(jù)庫(kù)管理
Redis用數(shù)字作為多個(gè)數(shù)據(jù)庫(kù)的實(shí)現(xiàn)埋哟,Redis默認(rèn)配置中是有16個(gè)數(shù)據(jù)庫(kù),編號(hào)從0-15郎汪,默認(rèn)使用0號(hào)數(shù)據(jù)庫(kù)
# 1. 切換數(shù)據(jù)庫(kù)
127.0.0.1:6379> get a
"a"
# select dbIndex 可以切換數(shù)據(jù)庫(kù)
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> get a
(nil)
Redis在3.0之后已經(jīng)開(kāi)始逐漸弱化這個(gè)功能赤赊,例如Redis的分布式實(shí)現(xiàn)Redis Cluster只允許使用0號(hào)數(shù)據(jù)庫(kù),只不過(guò)為了向下兼容老版本的數(shù)據(jù)庫(kù)功能煞赢,該功能沒(méi)有完全廢棄掉抛计,那么為什么要廢棄掉這個(gè)功能呢?
- Redis是單線程的照筑。如果使用多個(gè)數(shù)據(jù)庫(kù)吹截,那么這些數(shù)據(jù)庫(kù)仍然是使用一個(gè)CPU,彼此之間還是會(huì)受到影響的
- 多數(shù)據(jù)庫(kù)的使用方式凝危,會(huì)讓調(diào)試和運(yùn)維不同業(yè)務(wù)的數(shù)據(jù)庫(kù)變的困難波俄,假如有一個(gè)慢查詢存在,依然會(huì)影響其他數(shù)據(jù)庫(kù)蛾默,這樣會(huì)使得別的業(yè)務(wù)方定位問(wèn)題非常的困難
- 部分Redis的客戶端根本就不支持這種方式懦铺。即使支持,在開(kāi)發(fā)的時(shí)候來(lái)回切換數(shù)字形式的數(shù)據(jù)庫(kù)趴生,很容易弄亂
建議如果要使用多個(gè)數(shù)據(jù)庫(kù)功能阀趴,完全可以在一臺(tái)機(jī)器上部署多個(gè)Redis實(shí)例昏翰,彼此用端口來(lái)做區(qū)分苍匆,因?yàn)楝F(xiàn)代計(jì)算機(jī)或者服務(wù)器通常是有多個(gè)CPU的刘急。這樣既保證了業(yè)務(wù)之間不會(huì)受到影響,又合理地使用了CPU資源浸踩。
# 2. 清空數(shù)據(jù)庫(kù)
flushdb # 清空當(dāng)前數(shù)據(jù)庫(kù)的數(shù)據(jù)
flushall # 清空所有數(shù)據(jù)庫(kù)的數(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ù)庫(kù)的數(shù)據(jù)叔汁,其他數(shù)據(jù)庫(kù)的數(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ù)庫(kù)的數(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ù)检碗,但是也帶來(lái)兩個(gè)問(wèn)題:
- 這兩個(gè)命令會(huì)將所有數(shù)據(jù)清除据块,一旦誤操作后果不堪設(shè)想
- 如果當(dāng)前數(shù)據(jù)庫(kù)鍵值數(shù)量比較多,使用這兩個(gè)命令會(huì)存在阻塞Redis的可能性