redis實戰筆記(3)-第3章 Redis命令
阿新 • • 發佈:2017-08-23
chan 4.4 ges 打包 常用 重要 讀取 表操作 nio 第3章 Redis命令
本章主要內容
字符串命令、 列表命令和集合命令
散列命令和有序集合命令
發布命令與訂閱命令
其他命令
在每個不同的數據類型的章節裏, 展示的都是該數據類型所獨有的、 最具代表性的命令。 首先讓我們來看看, 除了GET和SET之外,
Redis的字符串還支持哪些命令。
3.1 字符串 在Redis裏面, 字符串可以存儲以下3種類型的值。 字節串( byte string) 。 整數。 浮點數。 除了自 增操作和自 減操作之外, Redis還擁有對字節串的其中一部分內容進行讀取或者寫入的操作(這些操作也可以用於整數或者浮點數,但這種用法並不常見) , 本書在第9章將展示如何使用這些操作來高效地將結構化數據打包( pack) 存儲到字符串鍵裏面。
3.2 列表 Redis的列表允許用戶從序列的兩端推入或者彈出元素, 獲取列表元素, 以及執行各種常見的列表操作。 除此之外,列表還可以用來存儲任務信息、 最近瀏覽過的文章或者常用聯系人信息。
3.3 集合 Redis的集合以無序的方式來存儲多個各不相同的元素, 用戶可以快速地對集合執行添加元素操作、 移除元素操作以及檢查一個元素是否存在於集合裏
3.4 散列 第1章提到過, Redis的散列可以讓用戶將多個鍵值對存儲到一個Redis鍵裏面。 從功能上來說, Redis為散列值提供了一些與字符串值相同的特性, 使得散列非常適用於將一些相關的數據存儲在一起。 我們可以把這種數據聚集看作是關系數據庫中的行, 或者文檔數據庫中的文檔。
3.7 其他命令 1.首先要介紹的是SORT命令; 2.之後要介紹是用於實現基本事務特性的MULTI命令和EXEC命令, 這兩個命令可以讓用戶將多個命令當作一個命令來執行; 3.最後要介紹的是幾個不同的自 動過期命令, 它們可以自 動刪除無用數據。 3.7.1 排序 SORT命令 可以根據字符串、 列表、 集合、 有序集合、 散列這5種鍵裏面存儲著的數據, 對列表、 集合以及有序集合進行排序。 使用SORT命令提供的選項可以實現以下功能: 1根據降序而不是默認的升序來排序元素; 2.將元素看作是數字來進行排序, 或者將元素看作是二進制字符串來進行排序(比如排序字符串‘ 110‘ 和‘ 12‘ 的結果就跟排序數字110和12的結果不一樣) ; 3.使用被排序元素之外的其他值作為權重來進行排序, 甚至還可以從輸入的列表、 集合、 有序集合以外的其他地方進行取值。
3.8 小結
3.1 字符串 在Redis裏面, 字符串可以存儲以下3種類型的值。 字節串( byte string) 。 整數。 浮點數。 除了自 增操作和自 減操作之外, Redis還擁有對字節串的其中一部分內容進行讀取或者寫入的操作(這些操作也可以用於整數或者浮點數,但這種用法並不常見) , 本書在第9章將展示如何使用這些操作來高效地將結構化數據打包( pack) 存儲到字符串鍵裏面。
很多鍵值數據庫只能將數據存儲為普通的字符串, 並且不提供任何字符串處理操作, 有一些鍵值數據庫允許用戶將字節追加到字符串的前面或者後面, 但是卻沒辦法像Redis一樣對字符串的子串進行讀寫。 從很多方面來講, 即使Redis只支持字符串結構, 並且只支持本節列出的字符串處理命令, Redis也比很多別的數據庫要強大得多; 通過使用子串操作和二進制位操作, 配合WATCH命令、 MULTI命令和EXEC命令(本書的3.7.2節將對這3個命令進行初步的介紹, 並在第4章對它們進行更深入的講解) , 用戶甚至可以自 己動手去構建任何他們想要的數據結構。第9章將介紹如何使用字符串去存儲一種簡單的映射, 這種映射可以在某些情況下節省大量內存。
3.2 列表 Redis的列表允許用戶從序列的兩端推入或者彈出元素, 獲取列表元素, 以及執行各種常見的列表操作。 除此之外,列表還可以用來存儲任務信息、 最近瀏覽過的文章或者常用聯系人信息。
對於阻塞彈出命令和彈出並推入命令, 最常見的用例就是消息傳遞( messaging) 和任務隊列( task queue) , 本書將在第6章對這兩個主題進行介紹。 練習: 通過列表來降低內存占用 略
3.3 集合 Redis的集合以無序的方式來存儲多個各不相同的元素, 用戶可以快速地對集合執行添加元素操作、 移除元素操作以及檢查一個元素是否存在於集合裏
3.4 散列 第1章提到過, Redis的散列可以讓用戶將多個鍵值對存儲到一個Redis鍵裏面。 從功能上來說, Redis為散列值提供了一些與字符串值相同的特性, 使得散列非常適用於將一些相關的數據存儲在一起。 我們可以把這種數據聚集看作是關系數據庫中的行, 或者文檔數據庫中的文檔。
第1章介紹的HGET命令和HSET命令分別是HMGET命令和HMSET命令的單參數版本
3.5 有序集合 和散列存儲著鍵與值之間的映射類似, 有序集合也存儲著成員與分值之間的映射, 並且提供了分值②處理命令, 以及根據分值大小有序地獲取( fetch) 或掃描( scan) 成員和分值的命令 本書曾在第1章使用有序集合實現過基於發表時間排序的文章列表和基於投票數量排序的文章列表
在表3-10展示的命令裏面, 有幾個是之前沒介紹過的新命令。 除了使用逆序來處理有序集合之外, ZREV*命令的工作方式和相對應的非逆序命令的工作方式完全一樣
圖3-1展示了對兩個輸入有序集合執行交集運算並得到輸出有序集合的過程, 這次交集運算使用的是默認的聚合函數sum, 所以輸出有序集合成員的分值都是通過加法計算得出的
圖3-2展示了使用聚合函數min執行並集運算的過程, min函數在多個輸入有序集合都包含同一個成員的情況下, 會將最小的那個分值設置為這個成員在輸出有序集合的分值 圖3-3展示了如何使用ZUNIONSTORE命令來將兩個有序集合和一個集合組合成一個有序集合
3.6 發布與訂閱 一般來說, 發布與訂閱(又稱pub/sub) 的特點是訂閱者( listener) 負責訂閱頻道( channel) , 發送者( publisher) 負責向頻道發送二進制字符串消息( binary string message) 。 每當有消息被發送至給定頻道時, 頻道的所有訂閱者都會收到消息。 我們也可以把頻道看作是電臺, 其中訂閱者可以同時收聽多個電臺, 而發送者則可以在任何電臺發送消息。 雖然Redis的發布與訂閱模式非常有用, 但本書只在這一節和8.5節中使用了這個模式, 這樣做的原因有以下兩個。 第一個原因和Redis系統的穩定性有關。 對於舊版Redis來說, 如果一個客戶端訂閱了某個或某些頻道, 但它讀取消息的速度卻不夠快的話, 那麽不斷積壓的消息就會使得Redis輸出緩沖區的體積變得越來越大, 這可能會導致Redis的速度變慢, 甚至直接崩潰。 也可能會導致Redis被 操作系統強制殺死, 甚至導致操作系統本身不可用。 新版的Redis不會 出現這種問題, 因為它會自 動斷開不符合client-output-bufferlimit pubsub配置選項要求的訂閱客戶端(本書第8章將對這個選項做 更詳細的介紹) 。 第二個原因和數據傳輸的可靠性有關。 任何網絡系統在執行操作時都可能會遇上斷線情況, 而斷線產生的連接錯誤通常會使得網絡連接兩端中的其中一端進行重新連接。 但是, 如果客戶端在執行訂閱操作的過程中斷線, 那麽客戶端將丟失在斷線期間發送的所有消息, 因此依靠頻道來接收消息的用戶可能會對Redis提供的PUBLISH命令和SUBSCRIBE命令的語義感到失望。 基於以上兩個原因 本書在第6章編寫了兩個不同的方法來實現可靠的消息傳遞操作, 這兩個方法除了可以處理網絡斷線之外, 還可以防止Redis因為消息積壓而耗費過多內存(這個方法即使對於舊版Redis也是有效的) 。 如果你喜歡簡單易用的PUBLISH命令和SUBSCRIBE命令, 並且能夠承擔可能會丟失一小部分數據的風險, 那麽你也可以繼續使用Redis提供的發布與訂閱特性, 而不是8.5節中提供的實現, 只要記得先把client-output-buffer-limit pubsub選項設置好就行了。
3.7 其他命令 1.首先要介紹的是SORT命令; 2.之後要介紹是用於實現基本事務特性的MULTI命令和EXEC命令, 這兩個命令可以讓用戶將多個命令當作一個命令來執行; 3.最後要介紹的是幾個不同的自 動過期命令, 它們可以自 動刪除無用數據。 3.7.1 排序 SORT命令 可以根據字符串、 列表、 集合、 有序集合、 散列這5種鍵裏面存儲著的數據, 對列表、 集合以及有序集合進行排序。 使用SORT命令提供的選項可以實現以下功能: 1根據降序而不是默認的升序來排序元素; 2.將元素看作是數字來進行排序, 或者將元素看作是二進制字符串來進行排序(比如排序字符串‘ 110‘ 和‘ 12‘ 的結果就跟排序數字110和12的結果不一樣) ; 3.使用被排序元素之外的其他值作為權重來進行排序, 甚至還可以從輸入的列表、 集合、 有序集合以外的其他地方進行取值。
SORT命令不僅可以對列表進行排序, 還可以對集合進行排序, 然後返回一個列表形式的排序結果。 代碼清單3-12除了展示如何使用alpha關鍵字參數對元素進行字符串排序之外, 還展示了如何基於外部數據對元素進行排序, 以及如何獲取並返回外部數據。 第7章將介紹如何組合使用集合操作和SORT命令: 當集合結構計算交集、 並集和差集的能力,與SORT命令獲取散列存儲的外部數據的能力相結合時, SORT命令將變得非常強大。 SORT是Redis中唯一一個可以同時處理3種不同類型的數據(列表、 集合以及有序集合?)的命令 3.7.2 基本的Redis事務 為了對相同或者不同類型的多個鍵執行操作, Redis有5個命令可以讓用戶在不被打斷( interruption) 的情況下對多個鍵執行操作, 它們分別是WATCH、 MULTI、 EXEC、 UNWATCH和DISCARD。 當Redis從一個客戶端那裏接收到MULTI命令時, Redis會將這個客戶端之後發送的所有命令都放入到一個隊列裏面, 直到這個客戶端發送EXEC命令為止, 然後Redis就會在不被打斷的情況下, 一個接一個地執行存儲在隊列裏面的命令 因為沒有使用事務, 所以3個線程都可以在執行自 減操作之前, 對notrans: 計數器執行自 增操作。 雖然代碼清單裏面通過休眠100毫秒的方式來放大了潛在的問題, 但如果我們確實需要在不受其他命令幹擾的情況下, 對計數器執行自 增操作和自 減操作, 那麽我們就不得不解決這個潛在的問題
盡管自 增操作和自 減操作之間有一段延遲時間, 但通過使用事務, 各個線程都可以在不被其他線程打斷的情況下, 執行各自 隊 列裏面的命令。 記住, Redis要在接收到EXEC命令之後, 才會執行那些位於MULTI和EXEC之間的入隊命令。 使用事務既有利也有弊, 本書的4.4節將對這個問題進行討論。 練習: 移除競爭條件 練習: 提高性能 3.7.3 鍵的過期時間 雖然過期時間特性對於清理緩存數據非常有用, 不過如果讀者翻一下本書的其他章節, 就會發現除了 6.2節、 7.1節和7.2節之外, 本書使用過期時間特性的情況並不多, 這主要和本書使用的結構類型有關。 在本書常用的命令當中, 只有少數幾個命令可以原子地為鍵設置過期時間,並且對於列表、 集合、 散列和有序集合這樣的容器( container) 來說,鍵過期命令只能為整個鍵設置過期時間, 而沒辦法為鍵裏面的單個元素設置過期時間(為了解決這個問題, 本書在好幾個地方都使用了存儲時間戳的有序集合來實現針對單個元素的過期操作) 練習: 使用 EXPIRE命令代替時間戳有序集合
3.8 小結
額:其他重要命令 1.SETEX SETEX key seconds value 將值 value 關聯到 key ,並將 key 的生存時間設為 seconds (以秒為單位)。 如果 key 已經存在, SETEX 命令將覆寫舊值。 這個命令類似於以下兩個命令: SET key value EXPIRE key seconds # 設置生存時間 不同之處是, SETEX 是一個原子性(atomic)操作,關聯值和設置生存時間兩個動作會在同一時間內完成,該命令在 Redis 用作緩存時,非常實用。 可用版本:>= 2.0.0 返回值: 設置成功時返回 OK 。 當 seconds 參數不合法時,返回一個錯誤。 # 在 key 不存在時進行 SETEX redis> SETEX cache_user_id 60 10086 OK redis> GET cache_user_id # 值 "10086" redis> TTL cache_user_id # 剩余生存時間 (integer) 49 # key 已經存在時,SETEX 覆蓋舊值 redis> SET cd "timeless" OK redis> SETEX cd 3000 "goodbye my love" OK redis> GET cd "goodbye my love" redis> TTL cd (integer) 2997 2.SETNX SETNX key value 將 key 的值設為 value ,當且僅當 key 不存在。 若給定的 key 已經存在,則 SETNX 不做任何動作。SETNX 是『SET if Not eXists』(如果不存在,則 SET)的簡寫。 可用版本:>= 1.0.0 返回值: 設置成功,返回 1 。 設置失敗,返回 0 。 redis> EXISTS job # job 不存在 (integer) 0 redis> SETNX job "programmer" # job 設置成功 (integer) 1 redis> SETNX job "code-farmer" # 嘗試覆蓋 job ,失敗 (integer) 0 redis> GET job # 沒有被覆蓋 "programmer" 3.用於key的 del,keys
redis實戰筆記(3)-第3章 Redis命令