redis命令參考

\color{red}{當(dāng)前命令集未注明統(tǒng)一參考版本 >= 1.x}


\color{green}{key}

  • 格式:DEL key [key ...]

  • 時(shí)間復(fù)雜度: 刪N為O ( N ) 帖汞,刪單個(gè)key渐苏,為O ( 1 )技健;

  • 返回值: 受影響的數(shù)量

刪除單個(gè) key

redis> SET name huangz
OK

redis> DEL name
(integer) 1

刪除一個(gè)不存在的 key

redis> EXISTS phone
(integer) 0

redis> DEL phone  # 失敗,沒有 key 被刪除
(integer) 0

同時(shí)刪除多個(gè) key

redis> SET name "redis"
OK

redis> SET type "key-value store"
OK

redis> SET website "redis.com"
OK

redis> DEL name type website
(integer) 3

\color{green}{keys}

  • 格式:keys pattern

\color{grey}{ 查找所有符合給定模式 pattern 的 key}

\color{grey}{KEYS * 匹配數(shù)據(jù)庫中所有 key }

\color{grey}{KEYS h?llo 匹配 hello 浪汪, hallo 和 hxllo 等}

\color{grey}{KEYS h*llo 匹配 hllo 和 heeeeello 等}

\color{grey}{KEYS h[ae]llo 匹配 hello 和 hallo 巴柿,但不匹配 hillo}

\color{grey}{特殊符號用\ 斜杠 \ 隔開}

警告:KEYS 的速度非常快死遭,但在一個(gè)大的數(shù)據(jù)庫中使用它仍然可能造成性能問題广恢,如 果你需要從一個(gè)數(shù)據(jù)集中查找特定的 key ,你最好還是用 Redis 的集合結(jié)構(gòu)(set)來代替呀潭。

  • 時(shí)間復(fù)雜度: O ( N ) N為key的size

  • 返回值: 匹配到的key集合

redis> MSET one 1 two 2 three 3 four 4 # 一次設(shè)置 4 個(gè) key
OK

redis> KEYS *o*
1) "four"
2) "two"
3) "one"

redis> KEYS t??
1) "two"

redis> KEYS t[w]*
1) "two"

redis> KEYS * # 匹配數(shù)據(jù)庫內(nèi)所有 key
1) "four"
2) "three"
3) "two"
4) "one"


\color{green}{randomkey}

  • 格式:randomkey

? 從當(dāng)前數(shù)據(jù)庫中隨機(jī)返回(不刪除)一個(gè) key

  • 時(shí)間復(fù)雜度: O ( 1 )钉迷;

  • 返回值: 受影響的數(shù)量

    ? 當(dāng)數(shù)據(jù)庫不為空時(shí)至非,返回一個(gè) key 。

    ? 當(dāng)數(shù)據(jù)庫為空時(shí)糠聪,返回 nil 睡蟋。

# 數(shù)據(jù)庫不為空
redis> MSET fruit "apple" drink "beer" food "cookies" # 設(shè)置多個(gè) key
OK

redis> RANDOMKEY
"fruit"

redis> RANDOMKEY
"food"

redis> KEYS * # 查看數(shù)據(jù)庫內(nèi)所有 key,證明 RANDOMKEY 并不刪除 key
1) "food"
2) "drink"
3) "fruit"

# 數(shù)據(jù)庫為空
redis> FLUSHDB # 刪除當(dāng)前數(shù)據(jù)庫所有 key
OK

redis> RANDOMKEY
(nil)

\color{green}{ ttl}

  • 格式:ttl key

  • 時(shí)間復(fù)雜度: O ( 1 )枷颊;

  • 返回值:

    當(dāng) key 不存在時(shí)戳杀,返回 -2 。

    當(dāng) key 存在但沒有設(shè)置剩余生存時(shí)間時(shí)夭苗,返回 -1 信卡。

    否則,以秒為單位题造,返回 key 的剩余生存時(shí)間傍菇。

    \color{red}{注:在 Redis 2.8 以前,當(dāng) key 不存在界赔,或者 key 沒有設(shè)置剩余生存時(shí)間時(shí)丢习,命令都返回 -1 。}

# 不存在的 key
redis> FLUSHDB
OK

redis> TTL key
(integer) -2

# key 存在淮悼,但沒有設(shè)置剩余生存時(shí)間
redis> SET key value
OK

redis> TTL key
(integer) -1

# 有剩余生存時(shí)間的 key
redis> EXPIRE key 10086
(integer) 1

redis> TTL key
(integer) 10084

\color{green}{ pttl}

  • 格式:pttl key

  • 參考版本:>= 2.6X

  • 時(shí)間復(fù)雜度: O ( 1 )咐低;

  • 返回值:

當(dāng) key 不存在時(shí),返回 -2 袜腥。

當(dāng) key 存在但沒有設(shè)置剩余生存時(shí)間時(shí)见擦,返回 -1 。

否則羹令,以毫秒為單位鲤屡,返回 key 的剩余生存時(shí)間。

\color{red}{注:在 Redis 2.8 以前福侈,當(dāng) key 不存在酒来,或者 key 沒有設(shè)置剩余生存時(shí)間時(shí),命令都返回 -1 }

# 不存在的 key
redis> FLUSHDB
OK

redis> PTTL key
(integer) -2

# key 存在肪凛,但沒有設(shè)置剩余生存時(shí)間
redis> SET key value
OK

redis> PTTL key
(integer) -1

# 有剩余生存時(shí)間的 key
redis> PEXPIRE key 10086
(integer) 1

redis> PTTL key
(integer) 6179

\color{green}{ exists}

  • 格式:exists key

  • 時(shí)間復(fù)雜度: O ( 1 )堰汉;

  • 返回值: 若 key 存在,返回 1 显拜,否則返回 0

redis> SET db "redis"
OK

redis> EXISTS db
(integer) 1

redis> DEL db
(integer) 1

redis> EXISTS db
(integer) 0

\color{green}{move}

  • 格式:move key db

\color{grey}{將當(dāng)前數(shù)據(jù)庫的 key 移動(dòng)到給定的數(shù)據(jù)庫 db 當(dāng)中}

\color{grey}{如果當(dāng)前數(shù)據(jù)庫(源數(shù)據(jù)庫)和給定數(shù)據(jù)庫(目標(biāo)數(shù)據(jù)庫)有相同名字的給定 key 衡奥,}
\color{grey}{或者key 不存在于當(dāng)前數(shù)據(jù)庫爹袁,那么 MOVE 沒有任何效果}

\color{grey}{因此远荠,也可以利用這一特性,將 MOVE 當(dāng)作鎖(locking)原語(primitive)}

  • 時(shí)間復(fù)雜度: O ( 1 )失息;
  • 返回值: 移動(dòng)成功返回 1 譬淳,失敗則返回 0
# key 存在于當(dāng)前數(shù)據(jù)庫
redis> SELECT 0 #redis 默認(rèn)使用數(shù)據(jù)庫 0档址,為了清晰起見,這里再顯式指定一次邻梆。
OK

redis> SET song "secret base - Zone"
OK

redis> MOVE song 1 # 將 song 移動(dòng)到數(shù)據(jù)庫 1
(integer) 1

redis> EXISTS song # song 已經(jīng)被移走
(integer) 0

redis> SELECT 1 # 使用數(shù)據(jù)庫 1
OK

redis:1> EXISTS song # 證實(shí) song 被移到了數(shù)據(jù)庫 1 (注意命令提示符變成了"redis:1"守伸,表明正在使用數(shù)據(jù)庫 1)
(integer) 1

# 當(dāng) key 不存在的時(shí)候
redis:1> EXISTS fake_key
(integer) 0

redis:1> MOVE fake_key 0 # 試圖從數(shù)據(jù)庫 1 移動(dòng)一個(gè)不存在的 key 到數(shù)據(jù)庫0,失敗
(integer) 0

redis:1> select 0 # 使用數(shù)據(jù)庫 0
OK

redis> EXISTS fake_key # 證實(shí) fake_key 不存在
(integer) 0

# 當(dāng)源數(shù)據(jù)庫和目標(biāo)數(shù)據(jù)庫有相同的 key 時(shí)
redis> SELECT 0 # 使用數(shù)據(jù)庫 0
OK

redis> SET favorite_fruit "banana"
OK

redis> SELECT 1 # 使用數(shù)據(jù)庫 1
OK

redis:1> SET favorite_fruit "apple"
OK

redis:1> SELECT 0 # 使用數(shù)據(jù)庫 0浦妄,并試圖將 favorite_fruit 移動(dòng)到數(shù)據(jù)庫 1
OK

redis> MOVE favorite_fruit 1 # 因?yàn)閮蓚€(gè)數(shù)據(jù)庫有相同的 key尼摹,MOVE 失敗
(integer) 0

redis> GET favorite_fruit # 數(shù)據(jù)庫 0 的 favorite_fruit 沒變
"banana"

redis> SELECT 1
OK

redis:1> GET favorite_fruit # 數(shù)據(jù)庫 1 的 favorite_fruit 也是
"apple"

\color{green}{rename}

  • 格式:randomkey

\color{grey}{將 key 改名為 newkey }

\color{grey}{當(dāng) key 和 newkey 相同,或者 key 不存在時(shí)剂娄,返回一個(gè)錯(cuò)誤}

\color{grey}{當(dāng) newkey 已經(jīng)存在時(shí)蠢涝, RENAME 命令將覆蓋舊值}

  • 時(shí)間復(fù)雜度: O ( 1 );
  • 返回值: 改名成功時(shí)提示 OK 阅懦,失敗時(shí)候返回一個(gè)錯(cuò)誤
# key 存在且 newkey 不存
redis> SET message "hello world"
OK

redis> RENAME message greeting
OK

redis> EXISTS message # message 不復(fù)存在
(integer) 0

redis> EXISTS greeting # greeting 取而代之
(integer) 1

# 當(dāng) key 不存在時(shí)和二,返回錯(cuò)誤
redis> RENAME fake_key never_exists
(error) ERR no such key

# newkey 已存在時(shí), RENAME 會(huì)覆蓋舊 newkey
redis> SET pc "lenovo"
OK

redis> SET personal_computer "dell"
OK

redis> RENAME pc personal_computer #這里相當(dāng)于value換了一個(gè)新的地址引用
OK

redis> GET pc
(nil)

redis:1> GET personal_computer # 原來的值 dell 被覆蓋了
"lenovo"

\color{green}{ renamenx}

  • 格式:renamenx key newkey

\color{grey}{當(dāng)且僅當(dāng) newkey 不存在時(shí)耳胎,將 key 改名為 newkey }

\color{grey}{當(dāng) key 不存在時(shí)惯吕,返回一個(gè)錯(cuò)誤}

  • 時(shí)間復(fù)雜度: O ( 1 );
  • 返回值:

修改成功時(shí)怕午,返回 1

如果 newkey 已經(jīng)存在废登,返回 0

# newkey 不存在,改名成功
redis> SET player "MPlyaer"
OK

redis> EXISTS best_player
(integer) 0

redis> RENAMENX player best_player
(integer) 1

# newkey 存在時(shí)郁惜,失敗
redis> SET animal "bear"
OK

redis> SET favorite_animal "butterfly"
OK

redis> RENAMENX animal favorite_animal
(integer) 0

redis> get animal
"bear"

redis> get favorite_animal
"butterfly"

\color{green}{type}

  • 格式:type key

\color{grey}{返回 key 所儲(chǔ)存的值的類型}

  • 時(shí)間復(fù)雜度: O ( 1 )钳宪;
  • 返回值:
none (key 不存在)
string (字符串)
list (列表)
set (集合)
zset (有序集)
hash (哈希表)
# 字符串
redis> SET weather "sunny"
OK

redis> TYPE weather
string

# 列表
redis> LPUSH book_list "programming in scala"
(integer) 1

redis> TYPE book_list
list

# 集合
redis> SADD pat "dog"
(integer) 1

redis> TYPE pat
set

\color{green}{ expire}

  • 格式:expire key seconds

\color{grey}{為給定 key 設(shè)置生存時(shí)間,當(dāng) key 過期時(shí)(生存時(shí)間為 0 )扳炬,它會(huì)被自動(dòng)刪除吏颖。}

\color{grey}{在 Redis 中,帶有生存時(shí)間的 key 被稱為『可揮發(fā)』(volatile)的}

\color{grey}{生存時(shí)間可以通過使用 DEL 命令來刪除整個(gè) key 來移除恨樟,或者被 SET 和 GETSET 命令覆寫(overwrite)半醉,這意味著,如果一個(gè)命令只是修改(alter)一個(gè)帶生存時(shí)間的 key 的值而不是用一個(gè)新的 key 值來代替(replace)它的話劝术,那么生存時(shí)間不會(huì)被改變缩多。}

\color{grey}{比如說,對一個(gè) key 執(zhí)行 INCR 命令养晋,對一個(gè)列表進(jìn)行 LPUSH 命令衬吆,或者對一個(gè)哈希表執(zhí)行 HSET 命令京革,這類操作都不會(huì)修改 key 本身的生存時(shí)間庸毫。}

\color{grey}{另一方面,如果使用 RENAME 對一個(gè) key 進(jìn)行改名火窒,那么改名后的 key 的生存時(shí)間和改名前一樣零酪。}
\color{grey}{RENAME 命令的另一種可能是冒嫡,嘗試將一個(gè)帶生存時(shí)間的 key 改名成另一個(gè)帶生存時(shí)間的 another_key 拇勃,這時(shí)舊的 another_key (以及它的生存時(shí)間)會(huì)被刪除,然后舊的 key 會(huì)改名為 another_key 孝凌,因此方咆,新的another_key 的生存時(shí)間也和原本的 key 一樣。}

\color{grey}{使用 PERSIST 命令可以在不刪除 key 的情況下蟀架,移除 key 的生存時(shí)間瓣赂,讓 key 重新成為一個(gè)『持久化』(persistent) key 。}

\color{grey}{**更新生存時(shí)間**}
\color{grey}{可以對一個(gè)已經(jīng)帶有生存時(shí)間的 key 執(zhí)行 EXPIRE 命令片拍,新指定的生存時(shí)間會(huì)取代舊的生存時(shí)間钩述。}

\color{grey}{**過期時(shí)間的精確度**}
\color{grey}{在 Redis 2.4 版本中,過期時(shí)間的延遲在 1 秒鐘之內(nèi) —— 也即是穆碎,就算 key 已經(jīng)過期牙勘,但它還是可能在過期后一秒鐘之內(nèi)被訪問到,而在新的 Redis 2.6 版本中所禀,延遲被降低到 1 毫秒之內(nèi)方面。}

\color{grey}{**Redis 2.1.3 之前的不同之處**}
\color{grey}{在 Redis 2.1.3 之前的版本中,修改一個(gè)帶有生存時(shí)間的 key 會(huì)導(dǎo)致整個(gè) key 被刪除色徘,這一行為是受當(dāng)時(shí)復(fù)制(replication)層的限制而作出的恭金,現(xiàn)在這一限制已經(jīng)被修復(fù)。}

  • 時(shí)間復(fù)雜度: O ( 1 )褂策;

  • 返回值:

    設(shè)置成功返回 1 横腿。

    當(dāng) key 不存在或者不能為 key 設(shè)置生存時(shí)間時(shí)(比如在低于 2.1.3 版本的 Redis 中你嘗試更新 key 的生存時(shí)間),返回 0

redis> SET cache_page "www.google.com"
OK

redis> EXPIRE cache_page 30 # 設(shè)置過期時(shí)間為 30 秒
(integer) 1

redis> TTL cache_page # 查看剩余生存時(shí)間
(integer) 23

redis> EXPIRE cache_page 30000 # 更新過期時(shí)間
(integer) 1

redis> TTL cache_page
(integer) 29996
  • 模式:導(dǎo)航會(huì)話

假設(shè)你有一項(xiàng) web 服務(wù)斤寂,打算根據(jù)用戶最近訪問的 N 個(gè)頁面來進(jìn)行物品推薦耿焊,并且假設(shè)用戶停止閱覽超過 60 秒,那么就清空閱覽記錄(為了減少物品推薦的計(jì)算量遍搞,并且保持推薦物品的新鮮度)罗侯。

這些最近訪問的頁面記錄,我們稱之為『導(dǎo)航會(huì)話』(Navigation session)溪猿,可以用 INCR 和 RPUSH 命令在 Redis 中實(shí)現(xiàn)它:每當(dāng)用戶閱覽一個(gè)網(wǎng)頁的時(shí)候钩杰,執(zhí)行以下代碼:

MULTI
 RPUSH pagewviews.user:<userid> http://.....
 EXPIRE pagewviews.user:<userid> 60
EXEC

如果用戶停止閱覽超過 60 秒,那么它的導(dǎo)航會(huì)話就會(huì)被清空诊县,當(dāng)用戶重新開始閱覽的時(shí)候讲弄,系統(tǒng)又會(huì)重新記錄導(dǎo)航會(huì)話,繼續(xù)進(jìn)行物品推薦依痊。

\color{green}{ pexpire}

  • 格式:pexpire key milliseconds

\color{grey}{這個(gè)命令和 EXPIRE 命令的作用類似避除,但是它以毫秒為單位設(shè)置 key 的生存時(shí)間,而不像 EXPIRE 命令那樣,以秒為單位}

  • 參考版本: >= 2.6X
  • 時(shí)間復(fù)雜度: O ( 1 )驹饺;
  • 返回值:

設(shè)置成功钳枕,返回 1

key 不存在或設(shè)置失敗缴渊,返回 0

redis> SET mykey "Hello"
OK

redis> PEXPIRE mykey 1500
(integer) 1

redis> TTL mykey # TTL 的返回值以秒為單位
(integer) 2

redis> PTTL mykey # PTTL 可以給出準(zhǔn)確的毫秒數(shù)
(integer) 1499

\color{green}{ expireat}

  • 格式:expireat key timestamp

\color{grey}{EXPIREAT 的作用和 EXPIRE 類似赏壹,都用于為 key 設(shè)置生存時(shí)間}

\color{grey}{不同在于 EXPIREAT 命令接受的時(shí)間參數(shù)是 UNIX 時(shí)間戳(unix timestamp)}

  • 參考版本: >= 1.2X
  • 時(shí)間復(fù)雜度: O ( 1 );
  • 返回值:

如果生存時(shí)間設(shè)置成功衔沼,返回 1

當(dāng) key 不存在或沒辦法設(shè)置生存時(shí)間蝌借,返回 0

redis> SET cache www.google.com
OK

redis> EXPIREAT cache 1355292000 # 這個(gè) key 將在 2012.12.12 過期
(integer) 1

redis> TTL cache
(integer) 45081860

\color{green}{ pexpireat}

  • 格式:pexpireat key milliseconds

\color{grey}{這個(gè)命令和 EXPIREAT 命令類似,但它以毫秒為單位設(shè)置 key 的過期 unix 時(shí)間戳指蚁,而不是像 EXPIREAT 那樣菩佑,以秒為單位}

  • 參考版本: >= 2.6X
  • 時(shí)間復(fù)雜度: O ( 1 );
  • 返回值:

如果生存時(shí)間設(shè)置成功凝化,返回 1 稍坯。

當(dāng) key 不存在或沒辦法設(shè)置生存時(shí)間時(shí),返回 0

redis> SET mykey "Hello"
OK

redis> PEXPIREAT mykey 1555555555005
(integer) 1

redis> TTL mykey # TTL 返回秒
(integer) 223157079

redis> PTTL mykey # PTTL 返回毫秒
(integer) 223157079318

\color{green}{ persist}

  • 格式:persist key

\color{grey}{移除給定 key 的生存時(shí)間搓劫,將這個(gè) key 從『可揮發(fā)』的(帶生存時(shí)間 key )轉(zhuǎn)換成『持久化』的(一個(gè)不帶生存時(shí)間瞧哟、永不過期的 key )。}

  • 參考版本: >= 2.2X
  • 時(shí)間復(fù)雜度: O ( 1 )枪向;
  • 返回值:

當(dāng)生存時(shí)間移除成功時(shí)勤揩,返回 1

如果 key 不存在或 key 沒有設(shè)置生存時(shí)間,返回 0

redis> SET mykey "Hello"
OK

redis> EXPIRE mykey 10 # 為 key 設(shè)置生存時(shí)間
(integer) 1

redis> TTL mykey
(integer) 10

redis> PERSIST mykey # 移除 key 的生存時(shí)間
(integer) 1

redis> TTL mykey
(integer) -1

\color{green}{ sort}

  • 格式:sort key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC | DESC] [ALPHA] [STORE destination]

\color{grey}{返回或保存給定列表秘蛔、集合陨亡、有序集合 key 中經(jīng)過排序的元素}

\color{grey}{排序默認(rèn)以數(shù)字作為對象,值被解釋為雙精度浮點(diǎn)數(shù)深员,然后進(jìn)行比較}

\color{grey}{**一般 SORT 用法** }

\color{grey}{最簡單的 SORT 使用方法是 SORT key }

\color{grey}{假設(shè) today_cost 是一個(gè)保存數(shù)字的列表负蠕, SORT 命令默認(rèn)會(huì)返回該列表值的遞增(從小到大)排序結(jié)果}

# 將數(shù)據(jù)一一加入到列表中
redis> LPUSH today_cost 30
(integer) 1

redis> LPUSH today_cost 1.5
(integer) 2

redis> LPUSH today_cost 10
(integer) 3

redis> LPUSH today_cost 8
(integer) 4

# 排序
redis> SORT today_cost
1) "1.5"
2) "8"
3) "10"
4) "30"

\color{grey}{當(dāng)數(shù)據(jù)集中保存的是字符串值時(shí),你可以用 ALPHA 修飾符(modifier)進(jìn)行排序倦畅。}

# 將數(shù)據(jù)一一加入到列表中
redis> LPUSH website "www.reddit.com"
(integer) 1

redis> LPUSH website "www.slashdot.com"
(integer) 2

redis> LPUSH website "www.infoq.com"
(integer) 3

# 默認(rèn)排序
redis> SORT website
1) "www.infoq.com"
2) "www.slashdot.com"
3) "www.reddit.com"

# 按字符排序
redis> SORT website ALPHA
1) "www.infoq.com"
2) "www.reddit.com"
3) "www.slashdot.com"

\color{grey}{如果你正確設(shè)置了 !LC_COLLATE 環(huán)境變量的話虐急,Redis 能識(shí)別 UTF-8 編碼。}

\color{grey}{排序之后返回的元素?cái)?shù)量可以通過 LIMIT 修飾符進(jìn)行限制滔迈。}

\color{grey}{LIMIT 修飾符接受兩個(gè)參數(shù): offset 和 count 止吁。}

\color{grey}{offset 指定要跳過的元素?cái)?shù)量, count 指定跳過 offset 個(gè)指定的元素之后燎悍,要返回多少個(gè)對象敬惦。}

\color{grey}{以下例子返回排序結(jié)果的前 5 個(gè)對象( offset 為 0 表示沒有元素被跳過)。}

# 將數(shù)據(jù)一一加入到列表中
redis> LPUSH rank 30
(integer) 1

redis> LPUSH rank 56
(integer) 2

redis> LPUSH rank 42
(integer) 3

redis> LPUSH rank 22
(integer) 4

redis> LPUSH rank 0
(integer) 5

redis> LPUSH rank 11
(integer) 6

redis> LPUSH rank 32
(integer) 7

redis> LPUSH rank 67
(integer) 8

redis> LPUSH rank 50
(integer) 9

redis> LPUSH rank 44
(integer) 10

redis> LPUSH rank 55
(integer) 11

# 排序
redis> SORT rank LIMIT 0 5 # 返回排名前五的元素
1) "0"
2) "11"
3) "22"
4) "30"
5) "32"

\color{grey}{修飾符可以組合使用谈山。以下例子返回降序(從大到小)的前 5 個(gè)對象}

redis> SORT rank LIMIT 0 5 DESC
1) "78"
2) "67"
3) "56"
4) "55"
5) "50"

\color{grey}{**使用外部 key 進(jìn)行排序**}

\color{grey}{有時(shí)候你會(huì)希望使用外部的 key 作為權(quán)重來比較元素俄删,代替默認(rèn)的對比方法。}

\color{grey}{假設(shè)現(xiàn)在有用戶(user)數(shù)據(jù)如下}

image.png

\color{grey}{id 數(shù)據(jù)保存在 key 名為 user_id 的列表中}

\color{grey}{name 數(shù)據(jù)保存在 key 名為 user_name_{id} 的列表中}

\color{grey}{level 數(shù)據(jù)保存在 user_level_{id} 的 key 中}

# 先將要使用的數(shù)據(jù)加入到數(shù)據(jù)庫中
# admin
redis> LPUSH user_id 1
(integer) 1

redis> SET user_name_1 admin
OK

redis> SET user_level_1 9999
OK

# huangz
redis> LPUSH user_id 2
(integer) 2

redis> SET user_name_2 huangz
OK

redis> SET user_level_2 10
OK

# jack
redis> LPUSH user_id 59230
(integer) 3

redis> SET user_name_59230 jack
OK

redis> SET user_level_59230 3
OK

# hacker
redis> LPUSH user_id 222
(integer) 4

redis> SET user_name_222 hacker
OK

redis> SET user_level_222 9999
OK

\color{grey}{如果希望按 level 從大到小排序 user_id ,可以使用以下命令:}

redis> SORT user_id BY user_level_* DESC
1) "222" # hacker
2) "1" # admin
3) "2" # huangz
4) "59230" # jack

但是有時(shí)候只是返回相應(yīng)的 id 沒有什么用畴椰,你可能更希望排序后返回 id 對應(yīng)的用戶名臊诊,這樣更友好一點(diǎn),使用 GET 選項(xiàng)可以做到這一點(diǎn)

redis> SORT user_id BY user_level_* DESC GET user_name_*
1) "hacker"
2) "admin"
3) "huangz"
4) "jack"

\color{grey}{可以多次地斜脂、有序地使用 GET 操作來獲取更多外部 key 抓艳。}

\color{grey}{比如你不但希望獲取用戶名,還希望連用戶的密碼也一并列出帚戳,可以使用以下命令}

# 先添加一些測試數(shù)據(jù)
redis> SET user_password_222 "hey,im in"
OK

redis> SET user_password_1 "a_long_long_password"
OK

redis> SET user_password_2 "nobodyknows"
OK

redis> SET user_password_59230 "jack201022"
OK

# 獲取 name 和 password
redis> SORT user_id BY user_level_* DESC GET user_name_* GET 
user_password_*
1) "hacker" # 用戶名
2) "hey,im in" # 密碼
3) "jack"
4) "jack201022"
5) "huangz"
6) "nobodyknows"
7) "admin"
8) "a_long_long_password"

# 注意 GET 操作是有序的玷或,GET user_name_* GET user_password_* 和 GET 
user_password_* GET user_name_*返回的結(jié)果位置不同
redis> SORT user_id BY user_level_* DESC GET user_password_* GET 
user_name_*
1) "hey,im in" # 密碼
2) "hacker" # 用戶名
3) "jack201022"
4) "jack"
5) "nobodyknows"
6) "huangz"
7) "a_long_long_password"
8) "admin"

GET 還有一個(gè)特殊的規(guī)則—— "GET #" ,用于獲取被排序?qū)ο?我們這里的例子是user_id)的當(dāng)前元素片任。

比如你希望 user_id 按 level 排序偏友,還要列出 id 、 name 和 password 对供,可以使用以下命令:

redis> SORT user_id BY user_level_* DESC GET # GET user_name_* GET 
user_password_*
1) "222" # id
2) "hacker" # name
3) "hey,im in" # password
4) "1"
5) "admin"
6) "a_long_long_password"
7) "2"
8) "huangz"
9) "nobodyknows"
10) "59230"
11) "jack"
12) "jack201022"

\color{grey}{**只獲取對象而不排序**}

\color{grey}{BY 修飾符可以將一個(gè)不存在的 key 當(dāng)作權(quán)重位他,讓 SORT 跳過排序操作。}

\color{grey}{該方法用于你希望獲取外部對象而又不希望引起排序開銷時(shí)使用产场。}

# 確保 fake_key 不存在
redis> EXISTS fake_key
(integer) 0

# 以 fake_key 作 BY 參數(shù)鹅髓,不排序,只 GET name 和 GET password
redis> SORT user_id BY fake_key GET # GET user_name_* GET 
user_password_*
1) "222" # id
2) "hacker" # user_name
3) "hey,im in" # password
4) "59230"
5) "jack"
6) "jack201022"
7) "2"
8) "huangz"
9) "nobodyknows"
10) "1"
11) "admin"
12) "a_long_long_password"

\color{grey}{**保存排序結(jié)果**}

默認(rèn)情況下涝动, SORT 操作只是簡單地返回排序結(jié)果迈勋,如果你希望保存排序結(jié)果,可以給STORE 選項(xiàng)指定一個(gè) key 作為參數(shù)醋粟,排序結(jié)果將以列表的形式被保存到這個(gè) key 上靡菇。(若指定 key 已存在,則覆蓋米愿。

redis> EXISTS user_info_sorted_by_level # 確保指定 key 不存在
(integer) 0

redis> SORT user_id BY user_level_* GET # GET user_name_* GET 
user_password_* STORE user_info_sorted_by_level # 排序
(integer) 12 # 顯示有 12 條結(jié)果被保存了

redis> LRANGE user_info_sorted_by_level 0 11 # 查看排序結(jié)果
1) "59230"
2) "jack"
3) "jack201022"
4) "2"
5) "huangz"
6) "nobodyknows"
7) "222"
8) "hacker"
9) "hey,im in"
10) "1"
11) "admin"
12) "a_long_long_password"

\color{grey}{一個(gè)有趣的用法是將 SORT 結(jié)果保存厦凤,用 EXPIRE 為結(jié)果集設(shè)置生存時(shí)間,這樣結(jié)果集就成了 SORT 操作的一個(gè)緩存育苟。}

\color{grey}{這樣就不必頻繁地調(diào)用 SORT 操作了较鼓,只有當(dāng)結(jié)果集過期時(shí),才需要再調(diào)用一次 SORT操作违柏。}

有時(shí)候?yàn)榱苏_實(shí)現(xiàn)這一用法博烂,你可能需要加鎖以避免多個(gè)客戶端同時(shí)進(jìn)行緩存重建(也就是多個(gè)客戶端,同一時(shí)間進(jìn)行 SORT 操作漱竖,并保存為結(jié)果集)禽篱,具體參見 SETNX 命令。

\color{grey}{**在 GET 和 BY 中使用哈希表** }

\color{grey}{可以使用哈希表特有的語法馍惹,在 SORT 命令中進(jìn)行 GET 和 BY 操作躺率。}

# 假設(shè)現(xiàn)在我們的用戶表新增了一個(gè) serial 項(xiàng)來為作為每個(gè)用戶的序列號
# 序列號以哈希表的形式保存在 serial 哈希域內(nèi)玛界。
redis> HMSET serial 1 23131283 2 23810573 222 502342349 59230 
2435829758
OK

# 用 serial 中值的大小為根據(jù),對 user_id 進(jìn)行排序
redis> SORT user_id BY *->serial
1) "59230"
2) "222"
3) "2"
4) "1"

\color{grey}{符號 "->" 用于分割哈希表的鍵名(key name)和索引域(hash field)悼吱,格式為"key->field"}

\color{grey}{除此之外慎框,哈希表的 BY 和 GET 操作和上面介紹的其他數(shù)據(jù)結(jié)構(gòu)(列表、集合后添、有序集合)沒有什么不同笨枯。}

  • 時(shí)間復(fù)雜度:

O(N+M*log(M)), N 為要排序的列表或集合內(nèi)的元素?cái)?shù)量吕朵, M 為要返回的元素?cái)?shù)量猎醇。

如果只是使用 SORT 命令的 GET 選項(xiàng)獲取數(shù)據(jù)而沒有進(jìn)行排序窥突,時(shí)間復(fù)雜度 O(N)努溃。

  • 返回值:

沒有使用 STORE 參數(shù),返回列表形式的排序結(jié)果阻问。

使用 STORE 參數(shù)梧税,返回排序結(jié)果的元素?cái)?shù)量。

\color{green}{ object}

  • 格式:object subcommand [arguments [arguments]]
    • \color{grey}{OBJECT 命令允許從內(nèi)部察看給定 key 的 Redis 對象称近。}

    • \color{grey}{它通常用在除錯(cuò)(debugging)或者了解為了節(jié)省空間而對 key 使用特殊編碼的情況第队。}

    • \color{grey}{當(dāng)將 Redis 用作緩存程序時(shí),你也可以通過 OBJECT 命令中的信息刨秆,決定 key 的驅(qū)逐策略(eviction policies)凳谦。}

? 1. \color{grey}{**OBJECT 命令有多個(gè)子命令:**}

  • \color{grey}{OBJECT REFCOUNT <key> 返回給定 key 引用所儲(chǔ)存的值的次數(shù)。此命令主要用于除錯(cuò)衡未。}
  • \color{grey}{OBJECT ENCODING <key> 返回給定 key 鎖儲(chǔ)存的值所使用的內(nèi)部表示(representation)}
  • \color{grey}{OBJECT IDLETIME <key> 返回給定 key 自儲(chǔ)存以來的空轉(zhuǎn)時(shí)間(idle尸执, 沒有被讀取也沒有被寫入),以秒為單位缓醋。}

? 2. \color{grey}{**對象可以以多種方式編碼:**}

  • \color{grey}{字符串可以被編碼為 raw (一般字符串)或 int (用字符串表示 64 位數(shù)字是為了節(jié)約空間)如失。}
  • \color{grey}{列表可以被編碼為 ziplist 或 linkedlist 。ziplist 是為節(jié)約大小較小的列表空間而作的特殊表示送粱。}
  • \color{grey}{集合可以被編碼為 intset 或者 hashtable 褪贵。 intset 是只儲(chǔ)存數(shù)字的小集合的特殊表示。}
  • \color{grey}{哈希表可以編碼為 zipmap 或者 hashtable 抗俄。 zipmap 是小哈希表的特殊表示脆丁。}
  • 有序集合可以被編碼為 ziplist 或者 skiplist 格式。ziplist 用于表示小的有序集合动雹,而 skiplist 則用于表示任何大小的有序集合槽卫。

假如你做了什么讓 Redis 沒辦法再使用節(jié)省空間的編碼時(shí)(比如將一個(gè)只有 1 個(gè)元素的集合擴(kuò)展為一個(gè)有 100 萬個(gè)元素的集合),特殊編碼類型(specially encoded types)會(huì)自動(dòng)轉(zhuǎn)換成通用類型(general type)洽胶。

  • 參考版本: >= 2.2X

  • 時(shí)間復(fù)雜度: O ( 1 )晒夹;

  • 返回值:

    REFCOUNT 和 IDLETIME 返回?cái)?shù)字裆馒。

    ENCODING 返回相應(yīng)的編碼類型

redis> SET game "COD" # 設(shè)置一個(gè)字符串
OK

redis> OBJECT REFCOUNT game # 只有一個(gè)引用
(integer) 1

redis> OBJECT IDLETIME game # 等待一陣。丐怯。喷好。然后查看空轉(zhuǎn)時(shí)間
(integer) 90

redis> GET game # 提取 game, 讓它處于活躍(active)狀態(tài)
"COD"

redis> OBJECT IDLETIME game # 不再處于空轉(zhuǎn)
(integer) 0

redis> OBJECT ENCODING game # 字符串的編碼方式
"raw"

redis> SET phone 15820123123 # 大的數(shù)字也被編碼為字符串
OK

redis> OBJECT ENCODING phone
"raw"

redis> SET age 20 # 短數(shù)字被編碼為 int
OK

redis> OBJECT ENCODING age
"int"

\color{green}{migrate}

  • 格式:migrate host port key destination-db timeout

    ? - 將 key 原子性地從當(dāng)前實(shí)例傳送到目標(biāo)實(shí)例的指定數(shù)據(jù)庫上读跷,一旦傳送成功梗搅, key 保證會(huì)出現(xiàn)在目標(biāo)實(shí)例上,而當(dāng)前實(shí)例上的 key 會(huì)被刪除效览。

    ? - 這個(gè)命令是一個(gè)原子操作无切,它在執(zhí)行的時(shí)候會(huì)阻塞進(jìn)行遷移的兩個(gè)實(shí)例,直到以下任意結(jié)果發(fā)生:遷移成功丐枉,遷移失敗哆键,等到超時(shí)。

    ? - 命令的內(nèi)部實(shí)現(xiàn)是這樣的:它在當(dāng)前實(shí)例對給定 key 執(zhí)行 DUMP 命令 瘦锹,將它序列化籍嘹,然后傳送到目標(biāo)實(shí)例,目標(biāo)實(shí)例再使用 RESTORE 對數(shù)據(jù)進(jìn)行反序列化弯院,并將反序列化所得的數(shù)據(jù)添加到數(shù)據(jù)庫中辱士;當(dāng)前實(shí)例就像目標(biāo)實(shí)例的客戶端那樣,只要看到 RESTORE 命令返回 OK 听绳,它就會(huì)調(diào)用 DEL 刪除自己數(shù)據(jù)庫上的 key 颂碘。

    ? - timeout 參數(shù)以毫秒為格式,指定當(dāng)前實(shí)例和目標(biāo)實(shí)例進(jìn)行溝通的最大間隔時(shí)間椅挣。這說明操作并不一定要在 timeout 毫秒內(nèi)完成头岔,只是說數(shù)據(jù)傳送的時(shí)間不能超過這個(gè) timeout 數(shù)。

    ? - MIGRATE 命令需要在給定的時(shí)間規(guī)定內(nèi)完成 IO 操作贴妻。如果在傳送數(shù)據(jù)時(shí)發(fā)生 IO 錯(cuò)誤切油,或者達(dá)到了超時(shí)時(shí)間,那么命令會(huì)停止執(zhí)行名惩,并返回一個(gè)特殊的錯(cuò)誤: IOERR 澎胡。

    ? - 當(dāng) IOERR 出現(xiàn)時(shí),有以下兩種可能:

          1. key 可能存在于兩個(gè)實(shí)例
          2. key 可能只存在于當(dāng)前實(shí)例
    

    ? - 唯一不可能發(fā)生的情況就是丟失 key 娩鹉,因此攻谁,如果一個(gè)客戶端執(zhí)行 MIGRATE 命令,并且不幸遇上 IOERR 錯(cuò)誤弯予,那么這個(gè)客戶端唯一要做的就是檢查自己數(shù)據(jù)庫上的 key 是否已經(jīng)被正確地刪除戚宦。

    ? - 如果有其他錯(cuò)誤發(fā)生,那么 MIGRATE 保證 key 只會(huì)出現(xiàn)在當(dāng)前實(shí)例中锈嫩。(當(dāng)然受楼,目標(biāo)實(shí)例的給定數(shù)據(jù)庫上可能有和 key 同名的鍵垦搬,不過這和 MIGRATE 命令沒有關(guān)系)。

  • 參考版本: >= 2.6X

  • 時(shí)間復(fù)雜度:

這個(gè)命令在源實(shí)例上實(shí)際執(zhí)行 DUMP 命令和 DEL 命令艳汽,在目標(biāo)實(shí)例執(zhí)行 RESTORE 命令猴贰,查看以上命令的文檔可以看到詳細(xì)的復(fù)雜度說明。

key 數(shù)據(jù)在兩個(gè)實(shí)例之間傳輸?shù)膹?fù)雜度為 O(N)

  • 返回值: 遷移成功時(shí)返回 OK 河狐,否則返回相應(yīng)的錯(cuò)誤
$ ./redis-server &
[1] 3557
...

$ ./redis-server --port 7777 &
[2] 3560
...

然后用客戶端連上 6379 端口的實(shí)例米绕,設(shè)置一個(gè)鍵,然后將它遷移到 7777 端口的實(shí)例上:

$ ./redis-cli
redis 127.0.0.1:6379> flushdb
OK

redis 127.0.0.1:6379> SET greeting "Hello from 6379 instance"
OK

redis 127.0.0.1:6379> MIGRATE 127.0.0.1 7777 greeting 0 1000
OK

redis 127.0.0.1:6379> EXISTS greeting # 遷移成功后 key 被刪除
(integer) 0

使用另一個(gè)客戶端馋艺,查看 7777 端口上的實(shí)例:

$ ./redis-cli -p 7777
redis 127.0.0.1:7777> GET greeting
"Hello from 6379 instance"

\color{green}{ dump}

  • 格式:dump key

序列化給定 key 栅干,并返回被序列化的值,使用 RESTORE 命令可以將這個(gè)值反序列化為Redis 鍵

序列化生成的值有以下幾個(gè)特點(diǎn):

  • 它帶有 64 位的校驗(yàn)和捐祠,用于檢測錯(cuò)誤碱鳞, RESTORE 在進(jìn)行反序列化之前會(huì)先檢查校驗(yàn)和。

  • 值的編碼格式和 RDB 文件保持一致雏赦。

  • RDB 版本會(huì)被編碼在序列化值當(dāng)中劫笙,如果因?yàn)?Redis 的版本不同造成 RDB 格式不兼容芙扎,那么Redis 會(huì)拒絕對這個(gè)值進(jìn)行反序列化操作星岗。

序列化的值不包括任何生存時(shí)間信息。

  • 參考版本: >= 2.6X
  • 時(shí)間復(fù)雜度:

查找給定鍵的復(fù)雜度為 O(1) 戒洼,對鍵進(jìn)行序列化的復(fù)雜度為 O(N*M) 俏橘,其中 N 是構(gòu)成key 的 Redis 對象的數(shù)量,而 M 則是這些對象的平均大小

如果序列化的對象是比較小的字符串圈浇,那么復(fù)雜度為 O(1)

  • 返回值:

如果 key 不存在寥掐,那么返回 nil

否則,返回序列化之后的值

redis> SET greeting "hello, dumping world!"
OK

redis> DUMP greeting "\x00\x15hello, dumping world!\x06\x00E\xa0Z\x82\xd8r\xc1\xde"

redis> DUMP not-exists-key
(nil)


\color{green}{未完待續(xù)磷蜀。召耘。。褐隆。}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末污它,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子庶弃,更是在濱河造成了極大的恐慌衫贬,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件歇攻,死亡現(xiàn)場離奇詭異固惯,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)缴守,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進(jìn)店門葬毫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來镇辉,“玉大人,你說我怎么就攤上這事贴捡√” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵栈暇,是天一觀的道長麻裁。 經(jīng)常有香客問我,道長源祈,這世上最難降的妖魔是什么煎源? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮香缺,結(jié)果婚禮上手销,老公的妹妹穿的比我還像新娘。我一直安慰自己图张,他們只是感情好锋拖,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著祸轮,像睡著了一般兽埃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上适袜,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天柄错,我揣著相機(jī)與錄音,去河邊找鬼苦酱。 笑死售貌,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的疫萤。 我是一名探鬼主播颂跨,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼扯饶!你這毒婦竟也來了恒削?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤帝际,失蹤者是張志新(化名)和其女友劉穎蔓同,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蹲诀,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡斑粱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了脯爪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片则北。...
    茶點(diǎn)故事閱讀 39,919評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡矿微,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出尚揣,到底是詐尸還是另有隱情涌矢,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布快骗,位于F島的核電站娜庇,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏方篮。R本人自食惡果不足惜名秀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望藕溅。 院中可真熱鬧匕得,春花似錦、人聲如沸巾表。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽集币。三九已至考阱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惠猿,已是汗流浹背羔砾。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留偶妖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓政溃,卻偏偏與公主長得像趾访,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子董虱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評論 2 354