佳木斯湛栽影视文化发展公司

主頁 > 知識庫 > Redis命令使用技巧之Keys的相關(guān)操作

Redis命令使用技巧之Keys的相關(guān)操作

熱門標簽:百度競價排名 呼叫中心市場需求 地方門戶網(wǎng)站 鐵路電話系統(tǒng) 服務(wù)外包 網(wǎng)站排名優(yōu)化 AI電銷 Linux服務(wù)器

前言

介紹完Redis連接相關(guān)命令后,再來介紹一下與Key相關(guān)的命令,Redis作為一個key-value數(shù)據(jù)庫,對Key進行操作是無法避免的。

KEYS 的速度非??欤谝粋€大的數(shù)據(jù)庫中使用它仍然可能造成性能問題,如果你需要從一個數(shù)據(jù)集中查找特定的 key ,你最好還是用 Redis 的集合結(jié)構(gòu)(set)來代替。

DEL

最早可用版本1.0.0

刪除指定的鍵值對,如果指定的key不存在,則忽略。DEL命令的時間復(fù)雜度是O(N),對于除字符串外的其他數(shù)據(jù)類型,命令的時間復(fù)雜度為O(M),M是值的元素的個數(shù)。所以,在生產(chǎn)環(huán)境盡量避免一次性刪除過多復(fù)雜數(shù)據(jù)類型的操作。

127.0.0.1:6379> SET key1 "jackey"
OK
127.0.0.1:6379> SET key2 "zhe"
OK
127.0.0.1:6379> DEL key1 key2 key3
(integer) 2

DUMP

最早可用版本2.6.0

使用一種Redis的格式序列化指定鍵存儲的值??捎檬褂肦ESTORE命令將這個值反序列化。

這種序列化格式有以下3個特點:

  • 它包含有64位的校驗和,用于錯誤檢查,RESTORE命令在反序列化之前會先檢查校驗和
  • 值的編碼格式和RDB文件的編碼格式相同
  • RDB的版本會被序列化到值中,因此,不同版本的Redis可能會因為不兼容RDB版本而拒絕反序列化

序列化的值不包含過期時間的相關(guān)信息,可以使用PTTL命令獲取當前值的存活時間。如果值不存在則會返回nil

127.0.0.1:6379> SET key1 "jackey"
OK
127.0.0.1:6379> DUMP key1
"\x00\x06jackey\b\x00\xec\x89'G'X\xfc:"
127.0.0.1:6379> DUMP not-exist-key
(nil)

DUMP時間復(fù)雜度分為兩部分:訪問key值的時間復(fù)雜度為O(1),而序列化值的時間復(fù)雜度為O(N*M),N是組成值的元素的數(shù)量,M是元素的平均大小。如果序列化比較短的字符串,則該命令的時間復(fù)雜度可以看做O(1)。

EXISTS

最早可用版本1.0.0

用于判斷key是否存在。3.0.3版本以后支持多參數(shù),即可以一次性判斷多個key,返回值是存在的key的數(shù)量。對于判斷單個key是否存在,會返回1或者0,因此,該命令是向后兼容的。

需要注意的是:如果參數(shù)中有重復(fù)的存在命令,則返回結(jié)果不會去重。

127.0.0.1:6379> SET key1 "jackey"
OK
127.0.0.1:6379> SET key2 "zhe"
OK
127.0.0.1:6379> EXISTS key1
(integer) 1
127.0.0.1:6379> EXISTS not-exist-key
(integer) 0
127.0.0.1:6379> EXISTS key1 key2 not-exist-key
(integer) 2
127.0.0.1:6379> EXISTS key1 key1 key1
(integer) 3

EXPIRE

最早可用版本1.0.0

為指定的key設(shè)置存活時間。存活時間會被DEL,SET,GETSET和所有的STORE命令刪除或者覆蓋。如果我們只修改key的值而不修改存活時間或者保存到一個新的key中,則原來的key的存活時間保持不變。如果使用RENAME對一個key重命名,那么原有key的存活時間會賦給新的key。

如果想要清除存活時間,使指定的key成為一個永久的key,則可以使用PERSIST命令,我們稍后會詳細介紹這個命令。

如果使用EXPIRE/PEXPIRE為某個key設(shè)置的存活時間為非正數(shù),或者使用EXPIREAT/PEXPIREAT設(shè)置了一個過去的時間,則這個key會直接被刪除。

127.0.0.1:6379> EXPIRE key1 -1
(integer) 1
127.0.0.1:6379> EXISTS key1
(integer) 0

對一個已經(jīng)有存活時間的key再次使用EXPIRE設(shè)置存活時間,則將key的存活時間更新,在許多應(yīng)用中我們都會用到這一點。

注意:在Redis的2.1.3版本之前,如果修改一個帶有存活時間的key的值,則會刪除整個key。

關(guān)于時間精度,Redis2.4版本中,一個key過期的一秒內(nèi)仍可以訪問,而到了2.6版本,這一時間已經(jīng)被精確到了1毫秒。因為從2.6版本開始,存活時間保存的是絕對時間(Unix的時間戳),而這就意味著,你的計算機的時間需要保證可靠,如果你將RDB文件放到另一臺機器上加載,當這兩臺機器的時間差距較大時,你就會發(fā)現(xiàn)可能有些key被刪除了或者有些key的存活時間被延長了。

下面我們在來討論一下Redis究竟是如何使key過期的,Redis的過期策略有兩種:一種是被動的,一種是主動的。

被動過期就是當客戶端訪問某個key,服務(wù)端會去檢查這個key的存活時間,判斷是否過期。當然,這種過期策略存在一定的問題,如果某個key一直都不訪問,就不會被發(fā)現(xiàn)它過期了,那么它將永遠“茍活”在內(nèi)存中。所以Redis會定期隨機的查看被設(shè)置過存活時間的key,看它們是否過期,如果過期了,就會及時清理掉。Redis每秒會做10次下面的操作:

  • 隨機查看20個設(shè)置過存活時間的key(從設(shè)置存活時間的set中?。?/li>
  • 刪除所有過期的key
  • 如果過期的key超過25%,那么會從第一步開始再執(zhí)行一次

EXPIREAT

最早可用版本1.2.0

此命令和EXPIRE的作用相同,不同之處是它的參數(shù)需要傳Unix時間戳(即從1970年1月1日起的毫秒數(shù))。

127.0.0.1:6379> GET key2
"zhe"
127.0.0.1:6379> EXPIREAT key2 1537733374
(integer) 1
127.0.0.1:6379> TTL key2
(integer) 12960

KEYS

最早可用版本1.0.0

這個命令會返回匹配到的所有key,時間復(fù)雜度為O(N)。在官方文檔中說,在入門級的筆記本電腦上,Redis掃描100萬條key只需要40毫秒,但是我們?nèi)匀灰苊庠谏a(chǎn)環(huán)境使用這個命令。特別是千萬不要使用KEYS *這樣的命令,因為你不知道生產(chǎn)環(huán)境存在多少key,這樣的命令有可能使你的生產(chǎn)環(huán)境的Redis陷入很長一段時間的不可用狀態(tài)。所以,請馬上刪除應(yīng)用層代碼中的KEYS命令或者抓緊時間更新自己的簡歷。

如果需要查找key,可以使用SCAN命令或者sets命令。

雖然我們非常不建議使用KEYS命令,但是它的匹配策略還是要介紹一下的:

?是單個字符的通配符,*是任意個數(shù)的通配符,[ae]會匹配到a或e,^e表示不匹配e,a-c表示匹配a或b或c,特殊符號使用\隔開。

127.0.0.1:6379> MSET key1hello jackey key2hello zhe age 3
OK
127.0.0.1:6379> KEYS key?hello
1) "key1hello"
2) "key2hello"
127.0.0.1:6379> KEYS k*
1) "key1hello"
2) "key2hello"
127.0.0.1:6379> KEYS *age*
1) "age"
127.0.0.1:6379> KEYS *
1) "age"
2) "key1hello"
3) "key2hello"

MIGRATE

最早可用版本2.6.0

這個命令用來將源實例的key以原子操作傳輸?shù)侥繕藢嵗?,然后將源實例的key刪除。相當于在源實例執(zhí)行了DUMP+DEL操作,在目標實例執(zhí)行了RESTORE操作。這一操作會阻塞進行傳輸?shù)膬蓚€實例,在傳輸過程中,key總會存在于一個實例中,除非發(fā)生超時錯誤。在3.2版本以后,MIGRATE可以將多個key作為管線一次性傳輸。

在執(zhí)行MIGRATE命令時,必須要設(shè)置一個超時時間,如果到了超時時間命令仍未執(zhí)行完,則會拋出一個IOERR。但返回這個錯誤時,兩個實例的狀態(tài)可能有兩種:要么兩個實例都存在指定的key,要么只有源實例存在指定的key。總之,key是不會丟失的。

從3.0.6版本開始,MIGRATE支持一次傳輸多個key,為了保證不過載或者出現(xiàn)環(huán)形操作,MIGRATE需要使用KEYS參數(shù),而原來指定的key的參數(shù)要被設(shè)置為空字符串。

MIGRATE 192.168.1.34 6379 "" 0 5000 KEYS key1 key2 key3

這里還有兩個選填參數(shù)需要介紹:一個是COPY,加上這個參數(shù)的話,傳輸完成后不會刪除源實例中的key。另一個是REPLACE,這個參數(shù)的作用是替換目標實例已存在的key。這兩個參數(shù)在3.0版本以后才可以使用。

MOVE

最早可用版本1.0.0

不知道大家還記不記得前文中我們提到過的SELECT命令,SELECT用來切換數(shù)據(jù)庫。使用MOVE命令就是將當前數(shù)據(jù)庫的key移動到指定的數(shù)據(jù)庫中,如果指定庫中已經(jīng)存在這個key或者當前庫不存在這個key,那么這個命令什么也不做。

127.0.0.1:6379> KEYS *
1) "age"
2) "key1hello"
3) "key2hello"
127.0.0.1:6379> MOVE age 1
(integer) 1
127.0.0.1:6379> KEYS *
1) "key1hello"
2) "key2hello"
127.0.0.1:6379> SELECT 1
OK
127.0.0.1:6379[1]> KEYS *
1) "age"

OBJECT

最早可用版本2.2.3

OBJECT用來查看Redis對象內(nèi)部的相關(guān)信息。這一命令在調(diào)試時經(jīng)常被使用。下面我們來介紹OBJECT命令的具體用法:

  • OBJECT REFCOUNT key:返回指定key的值的引用數(shù)量
  • OBJECT ENCODING key:返回指定key的內(nèi)部存儲使用的編碼格式
  • OBJECT IDLETIME key:返回指定key的空閑時間(有多長時間沒有被讀寫),目前最小精度為10秒,這一命令經(jīng)常在Redis淘汰機制中使用(淘汰策略為LRU或noeviction)
  • OBJECT FREQ key:返回指定key訪問頻率的對數(shù),當淘汰策略為LFU時,這一命令會被用到
  • OBJECT HELP:返回幫助信息

對象的編碼格式也有很多種:

  • Strings會被編碼為raw或int
  • Lists會被編碼為ziplist或linkedlist
  • Sets會被編碼為intset或hashtable
  • Hashs會被編碼為ziplist或hashtable
  • Sorted Sets會被編碼為ziplist或skiplist
127.0.0.1:6379> OBJECT REFCOUNT key1hello
(integer) 1
127.0.0.1:6379> OBJECT IDLETIME key2hello
(integer) 3637
127.0.0.1:6379> OBJECT ENCODING age
"int"

PERSIST

最早可用版本2.2.0

刪除指定key的過期時間,使之變成永久的key。

PEXPIRE

最早可用版本2.6.0

PEXPIRE的作用和EXPIRE一樣,只不過參數(shù)中的時間單位是毫秒。

PEXPIREAT

最早可用版本2.6.0

作用和EXPIREAT相同,參數(shù)同樣是毫秒。

PTTL

最早可用版本2.6.0

返回指定key的剩余存活時間的毫秒數(shù)。2.8以后的版本返回值有些變化,如果key不存在,則返回-2;如果key是永久的,則返回-1。

RANDOMKEY

最早可用版本1.0.0

此命令用于從當前數(shù)據(jù)庫返回一個隨機的key。

RENAME

最早可用版本1.0.0

重命名一個key。如果key不存在,則會返回錯誤。而如果新的key已經(jīng)存在,則此命令會覆蓋原來的key(它其實是執(zhí)行了一個隱式的DEL命令,因此如果原來的key存儲的對象很大的話, 刪除操作延時會很高)。在3.2版本以前,如果源key和目標key相同的話,會報錯。

RENAMENX

如果新的key不存在的話,重命名key,如果存在的話返回0,成功返回1。

RESTORE

最早可用版本2.6.0

用法:RESTORE key ttl serialized-value [REPLACE]

此命令是將一組數(shù)據(jù)反序列化,并存到key。如果ttl是0,則key是永久的。在Redis3.0版本以后,如果不使用REPLACE參數(shù)并且key已經(jīng)存在,則會返回一個錯誤“Target key name is busy”。

SCAN

最早可用版本2.8.0

用法:SCAN cursor MATCH pattern COUNT count

其中cursor為游標,MATCH和COUNT為可選參數(shù)。

SCAN命令和SSCAN、HSCAN、ZSCAN命令都用于增量的迭代元素集,它每次返回小部分數(shù)據(jù),不會像KEYS那樣阻塞Redis。SCAN命令是基于游標的,每次調(diào)用后,都會返回一個游標,用于下一次迭代。當游標返回0時,表示迭代結(jié)束。

SCAN每次返回的數(shù)量并不固定,也有可能返回數(shù)據(jù)為空。另外,SCAN命令和KEYS命令一樣支持匹配。

我們在Redis里存入10000個key用于測試。

結(jié)果如下:

127.0.0.1:6379> scan 0 match key24* count 1000
1) "1688"
2) 1) "key2411"
 2) "key2475"
 3) "key2494"
 4) "key2406"
 5) "key2478"
127.0.0.1:6379> scan 1688 match key24* count 1000
1) "2444"
2) 1) "key2458"
 2) "key249"
 3) "key2407"
 4) "key2434"
 5) "key241"
 6) "key2497"
 7) "key2435"
 8) "key2413"
 9) "key2421"
 10) "key248"
127.0.0.1:6379> scan 2444 match key24* count 1000
1) "818"
2) 1) "key2459"
 2) "key2462"
 3) "key2409"
 4) "key2454"
 5) "key2431"
 6) "key2423"
 7) "key2476"
 8) "key2428"
 9) "key2493"
 10) "key2420"
127.0.0.1:6379> scan 818 match key24* count 1000
1) "9190"
2) 1) "key2402"
 2) "key2415"
 3) "key2429"
 4) "key2424"
 5) "key2425"
 6) "key2400"
 7) "key2472"
 8) "key2479"
 9) "key2448"
 10) "key245"
 11) "key2487"
 12) "key2430"
 13) "key2405"
127.0.0.1:6379> scan 9190 match key24* count 1000
1) "12161"
2) 1) "key2488"
 2) "key2437"
 3) "key2404"
 4) "key2440"
 5) "key2461"
 6) "key2416"
 7) "key2436"
 8) "key2403"
 9) "key2460"
 10) "key2452"
 11) "key2449"
 12) "key2482"
127.0.0.1:6379> scan 12161 match key24* count 1000
1) "11993"
2) 1) "key2483"
 2) "key2491"
 3) "key242"
 4) "key2466"
 5) "key2446"
 6) "key2465"
 7) "key243"
 8) "key2438"
 9) "key2457"
 10) "key246"
 11) "key2422"
 12) "key2418"
127.0.0.1:6379> scan 11993 match key24* count 1000
1) "7853"
2) 1) "key2498"
 2) "key2451"
 3) "key2439"
 4) "key2495"
 5) "key2408"
 6) "key2410"
127.0.0.1:6379> scan 7853 match key24* count 1000
1) "5875"
2) 1) "key2486"
 2) "key2490"
 3) "key244"
 4) "key2401"
 5) "key2463"
 6) "key2481"
 7) "key2477"
 8) "key2468"
 9) "key2433"
 10) "key2489"
 11) "key2455"
 12) "key2426"
 13) "key24"
 14) "key2450"
 15) "key2414"
 16) "key2442"
 17) "key2473"
 18) "key2467"
 19) "key2469"
 20) "key2456"
127.0.0.1:6379> scan 5875 match key24* count 1000
1) "14311"
2) 1) "key2453"
 2) "key2492"
 3) "key2480"
 4) "key2427"
 5) "key2443"
 6) "key2417"
 7) "key2432"
 8) "key240"
 9) "key2445"
 10) "key2484"
 11) "key2444"
 12) "key247"
 13) "key2485"
127.0.0.1:6379> scan 14311 match key24* count 1000
1) "16383"
2) 1) "key2441"
 2) "key2474"
 3) "key2447"
 4) "key2471"
 5) "key2470"
 6) "key2464"
 7) "key2412"
 8) "key2419"
 9) "key2499"
 10) "key2496"
127.0.0.1:6379> scan 16383 match key24* count 1000
1) "0"
2) (empty list or set)

可以看到雖然我們設(shè)置的count為1000,但Redis每次返回的數(shù)值只有10個左右。

SORT

最早可用版本1.0.0

當有N個元素需要排序,并且要返回M個元素時,SORT命令的時間復(fù)雜度為O(N+M*log(M))

此命令用于返回或保存list,set和sorted set的鍵,默認將數(shù)字或者可排序的key進行排序,Redis會將其視為雙精度浮點數(shù)。

如果想要對字符串按字典順序排序,可以使用ALPHA參數(shù)。

如果想要按照外部字段進行排序,可以使用BY參數(shù)。

TOUCH

最早可用版本3.2.1

修改某一個或多個key的最后訪問時間,如果key不存在,則忽略。

TTL

最早可用版本1.0.0

返回指定key的剩余存活時間,單位為秒。

在2.6版本及以前,如果key不存在或者是永久key,都會返回-1。從2.8版本開始,如果key不存在,則返回-2,如果key為永久key,則返回-1。

TYPE

最早可用版本1.0.0

返回key存儲的值的類型。類型即為我們在Redis基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)一文中描述的5中數(shù)據(jù)類型。

String

String是最基本的,也是最常用的類型。它是二進制安全的,也就是說,我們可以將對象序列化成json字符串作為value值存入Redis。在分配內(nèi)存時,Redis會為一個字符串分配一些冗余的空間,以避免因字符串的值改變而出現(xiàn)頻繁的內(nèi)存分配操作。當字符串長度小于1M時,每次擴容都會加倍現(xiàn)有空間,當長度大于1M時,每次擴容,增加1M,Redis字符串的最大長度是512M。

Hash

Hash是鍵值對集合,相當于Java中的HashMap,實際結(jié)構(gòu)也和HashMap一樣,是數(shù)組+鏈表的結(jié)構(gòu)。所不同的是擴容的方式不同,HashMap是進行一次rehash,而Redis為了不阻塞服務(wù),會創(chuàng)建一個新的數(shù)組,在查詢時會同時查詢兩個Hash,然后在逐漸將舊的Hash內(nèi)容轉(zhuǎn)移到新的中去。一個Hash最大可以存儲232-1個鍵值對。

List

List相當于Java中的LinkedList,它的插入和刪除操作的時間復(fù)雜度為O(1),而查詢操作的時間復(fù)雜度為O(n)。我們可以利用List的rpush、rpop、lpush和lpop命令來構(gòu)建隊列或者棧。列表最多可以存儲232-1個元素。

Set

Set是String類型的無序集合,并且元素唯一,相當于Java中的HashSet,它的插入、刪除、查詢操作的時間復(fù)雜度都是O(1)。其最大元素數(shù)也是232-1個。

zset

zset可以看做是Java中SortedSet和HashMap的結(jié)合,一方面它不允許元素重復(fù),另一方面,它通過score為每個元素進行排序。

UNLINK

最早可用版本4.0.0

這個命令和DEL類似,會刪除指定的key。所不同的是,此命令的時間復(fù)雜度為O(1),它先將key從keyspace中刪除,此時指定的key已經(jīng)刪除,但是內(nèi)存沒有釋放。所以,這個命令會在另一個線程中做釋放內(nèi)存的操作。這一步的操作時間復(fù)雜度為O(N)。

WAIT

最早可用版本3.0.0

這個命令會阻塞客戶端,直到前面所有的寫操作都完成并且保存了指定數(shù)量的副本。該命令總會返回副本數(shù)量或者超時。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

您可能感興趣的文章:
  • Redis遍歷所有key的兩個命令(KEYS 和 SCAN)
  • redis keys與scan命令的區(qū)別說明
  • 解決spring中redistemplate不能用通配符keys查出相應(yīng)Key的問題
  • 在RedisTemplate中使用scan代替keys指令操作
  • Redis的KEYS 命令千萬不能亂用
  • Redis不使用 keys 命令獲取鍵值信息的方法
  • redis 用scan指令 代替keys指令(詳解)
  • 淺談Redis的keys命令到底有多慢

標簽:銅川 蘭州 衡水 仙桃 湘潭 黃山 崇左 湖南

巨人網(wǎng)絡(luò)通訊聲明:本文標題《Redis命令使用技巧之Keys的相關(guān)操作》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266
    获嘉县| 富平县| 平安县| 万源市| 沭阳县| 双柏县| 吉安市| 汶川县| 穆棱市| 贞丰县| 泰顺县| 驻马店市| 德保县| 平果县| 定日县| 偏关县| 仁寿县| 太湖县| 东乡| 广安市| 洛隆县| 达州市| 阜南县| 宁安市| 吉隆县| 临沧市| 陈巴尔虎旗| 永丰县| 安徽省| 靖西县| 平定县| 佛冈县| 淅川县| 乐平市| 顺平县| 涟源市| 邮箱| 平顶山市| 扬州市| 乌什县| 松滋市|