摘要:上一篇文章實戰第三章命令第六節發布與訂閱下一篇文章實戰第四章數據安全與性能保障第節持久化選項到目前為止,本章介紹了提供的種結構以及的發布與訂閱模式。
上一篇文章:Python--Redis實戰:第三章:Redis命令:第六節:發布與訂閱
下一篇文章:Python--Redis實戰:第四章:數據安全與性能保障:第1節:持久化選項
到目前為止,本章介紹了Redis提供的5種結構以及Redis的發布與訂閱模式。本節將要介紹的命令則可以用于處理多種類型的數據:首先要介紹的是可以同時處理字符串、集合、列表和散列的sort命令;之后要介紹的是用于實現基本事務特性的multi命令和exec命令,這兩個命令可以讓用戶將多個命令當做一個命令來執行;最后要介紹的是幾個不同的自動過期命令,他們可以自動刪除無用的數據。
閱讀本節有助于讀者更好的理解如何同時組合和操作多種數據類型。
排序Redis的排序操作和其他編程語言的排序操作一樣,都可以根據某種比較規則對一系列元素進行有序排列。負責執行排序操作的sort命令可以根據字符串、列表、集合、有序集合、散列這5種鍵Kim存儲的數據,對列表、集合以及有序集合進行排序。如果讀者之前曾經使用過關系數據庫的話,那么可以將soft命令看做是sql語言里的order by。
下表展示了sort命令的定義:
命令 | 用例 | 用例描述 |
---|---|---|
soft | soft source-key [by pattern] [limit offset count] [get pattern get pattern ...]] [asc/desc] [alph] [store dest-key] | 根據給定的選項,對輸入列表、集合或者有序集合進行排序,然后返回或者存儲排序的結果。 |
使用sort命令提供的選項可以實現以下功能:
根據降序而不是默認的升序來排列元素;
將元素看作是數字來進行排序,或者將元素看作是二進制字符串來進行排序(比如排序字符串"110"和"12"的排序結果就跟排序數字110和12的結果不一樣);
使用被排序元素之外的其他值作為權重進行排序,甚至還可以從輸入的列表、集合、有序集合以外的其他地方進行取值。
實例import redis # 導入redis包包 # 與本地redis進行鏈接,地址為:localhost,端口號為6379 r = redis.StrictRedis(host="localhost", port=6379) r.delete("sort-input") #首先將一些元素添加到列表里面 print(r.rpush("sort-input",23,15,110,7)) #根據數字大小對元素進行排序 print(r.sort("sort-input")) #根據字母順序對元素進行排序 print(r.sort("sort-input",alpha=True)) #添加一些用于執行排序操作和獲取操作的附加數據 print(r.hset("d-7","field",5)) print(r.hset("d-15","field",1)) print(r.hset("d-23","field",9)) print(r.hset("d-110","field",3)) #將散列的域(field)用作權重,對sort-input列表進行排序 print(r.sort("sort-input",by="d-*->field")) #獲取外部數據,并將它們用作命令的返回值,而不是返回被排序的數據 print(r.sort("sort-input",by="d-*->field",get="d-*->field"))
運行結果:
4 [b"7", b"15", b"23", b"110"] [b"110", b"15", b"23", b"7"] 0 0 0 0 [b"15", b"110", b"7", b"23"] [b"1", b"3", b"5", b"9"]
最開頭的幾行代碼設置了一些初始數據,然后對這些數據進行了數值排序和字符串排序,最后的代碼演示了如果通過sort命令的特殊語法來將散列存儲的數據作為權重進行排序,以及怎樣獲取并返回散列存儲的數據。
sort命令不僅可以對列表進行排序,還可以對集合進行排序,然后返回一個列表形式的排序結果。上述實例除了展示了如果使用alpha關鍵字參數對元素進行字符串排序之外,還展示了如果基于外部數據對元素進行排序,以及如何獲取并返回外部數據。
后面講介紹如何組合使用集合操作和sort命令:當集合結構計算交集、并集和差集的能力,與sort命令獲取散列存儲的外部數據的能力相結合時,sort命令將變得非常強大。
盡管sort是Redis中唯一一個可以同時處理3種不同類型的數據的命令,但基本的Redis事務同樣可以讓我們在一連串不斷執行的命令里面操作多種不同類型的數據。
基本的Redis事務有時候為了同時處理多個結構,我們需要向Redis發送多個命令。盡管Redis有幾個可以在兩個鍵之間復制或者移動元素,但卻沒有那種可以在兩個不同類型之間移動元素的命令(雖然可以使用zunionstore命令將元素從一個集合復制到一個有序集合)。為了對相同或者不同類型的多個鍵執行操作,Redis有5個命令可以讓用戶在不被打斷(interruption)的情況下對多個鍵執行操作,它們分別是watch、multi、exec、unwatch、discard。
這一節中介紹最基本的Redis事務用法,其中只會用到multi命令和exec命令。
什么是Redis的基本事務Redis的基本事務需要用到multi命令和exec命令,這種事務可以讓一個客戶端在不被其他客戶端打斷的情況下執行多個命令。和關系數據庫那種可以在執行的過程中進行回滾(rollback)的事務不同,在Redis里面,被multi命令和exec命令包圍的所有命令會一個接一個的執行,直到所有命令都執行完畢。當一個事務執行完畢之后,Redis才會處理其他客戶端的命令。
要在Redis里面執行事務,我們首先需要執行multi命令,然后輸入那些我們想要在事務里面執行的命令,最后再執行exec命令。當Redis從一個客戶端那里接受到multi命令時,Redis會將這個客戶端之后發送的所有命令都放入到一個隊列里面,直到這個客戶端發送exec命令為止,然后Redis就會在不被打斷的情況下,一個接一個地執行存儲在隊列里面的命令。從語義上來說,Redis事務在Python客戶端上面是由流水線(pipelien)實現:對連接對象用pipeline()方法將創建一個事務,在一切正常的情況下,客戶端會自動地使用multi和exec包裹起用戶輸入的多個命令。此處,為了減少Redis與客戶端之間的通信往返次數,提升執行多個命令時的性能,Python的Redis客戶端會存儲起事務包含的多個命令,然后在事務執行時一次性地將所有命令都發送給Redis。
跟介紹publish命令和subscribe命令時的情況一樣,要展示事務執行結果,最簡單的方法就是將事務放到線程里執行。
下面代碼展示了在沒有使用事務的情況下,執行并行(parallel)自增操作的結果:
import redis # 導入redis包包 import time,threading # 與本地redis進行鏈接,地址為:localhost,端口號為6379 r = redis.StrictRedis(host="localhost", port=6379) r.delete("notrans:") def notrans(): #對"notrans:"計數器執行自增操作并打印操作的執行結果 print(r.incr("notrans:")) #等待100毫秒 time.sleep(.1) #對"notrans:"計數器執行自減操作。 r.incr("notrans:",-1) if __name__ == "__main__": # 啟動3個線程來執行沒有被事務包裹的自增、休眠和自減操作 for i in range(3): threading.Thread(target=notrans).start() # 等待500毫秒,讓操作有足夠的時間完成 time.sleep(.5)
結果:
1 2 3
因為沒有使用事務,所以三個線程都可以在執行自減操作之前,對notrans:計數器執行自增操作。雖然代碼里面通過休眠100毫秒放大了潛在問題,但如果我們確實需要在不受其它命令干擾的情況下,對計數器執行自增操作和自減操作,那么我們就不得不解決這個潛在問題。
下面代碼使用事務來執行相同的操作:
import redis # 導入redis包包 import time,threading # 與本地redis進行鏈接,地址為:localhost,端口號為6379 r = redis.StrictRedis(host="localhost", port=6379) r.delete("trans:") def notrans(): #創建一個事務型(transactional)流水線對象 pipeline=r.pipeline() #把針對"trans:"計數器的自增操作放入隊列 pipeline.incr("trans:") #等待100毫秒 time.sleep(.1) #把針對"trans:"計數器的自減操作放入隊列 pipeline.incr("trans:",-1) #執行被事務包裹的命令,并打印自增操作的執行結果 print(pipeline.execute()[0]) if __name__ == "__main__": # 啟動3個線程來執行沒有被事務包裹的自增、休眠和自減操作 for i in range(3): threading.Thread(target=notrans).start() # 等待500毫秒,讓操作有足夠的時間完成 time.sleep(.5)
結果:
1 1 1
可以看出,盡管自增操作和自減操作直接有一段延遲時間,但通過使用事務,各個線程都可以在不被其它線程打斷的情況下,執行各自隊列里面的命令。記住,Redis要在接收到Exec命令之后,才會執行那些位于multi和exec之間的入隊命令。
在使用Redis存儲數據的時候,有些數據僅在一段很短的時間內有用,雖然我們可以在數據的有效期過了之后刪除無用的數據,但更好的辦法是使用Redis提供的鍵過期操作來自動刪除無用數據。
鍵的過期時間在使用Redis存儲數據的時候,有些數據可能在某個時間點之后就不再有用了,用戶可以使用DEL命令顯示刪除這些無用數據,也可以通過Redis的過期時間(expiration)特征來讓一個鍵再給定的時限(timeout)之后自動被刪除。當我們說一個鍵【帶有生存時間】(time to live)或者一個鍵【會在特定時間之后過期】時,我們指的是Redis會在這個鍵的過期時間到達時自動刪除該鍵。
雖然過期時間特性對于清理緩存數據非常有用,不過通常只有少數幾個命令可以原子地為鍵設置過期時間,并且對于列表、集合、散列和有序集合這樣的容器來說,鍵過期命令只能為整個鍵設置過期時間,而沒辦法為鍵里面的單個元素設置過期時間(為了解決這個問題,可以使用存儲時間戳的有序集合來實現針對的那個元素的過期操作)。
本節將對那些可以在給定時限或者給定時間之后,自動刪除過期鍵的Redis命令進行介紹。通過閱讀本節,讀者可以學會如何使用過期操作來自動刪除過期數據并降低Redis的內存占用。
下表列出了Redis提供的用于為鍵設置過期時間的命令,已經查看鍵的過期時間的命令:
命令 | 示例 | 描述 |
---|---|---|
persist | persist key-name | 移除鍵的過期時間 |
ttl | ttl key-name | 查看給定鍵距離過期還有多少秒 |
expire | expire key-name seconds | 讓給定鍵再指定的秒數之后過期 |
expireat | expireat key-name timestamp | 將給定鍵的過期時間設置為給定的UNIX時間戳。 |
pttl | pttl key-name | 查看給定鍵距離過期時間還有多少毫秒,這個命令在Redis2.6或以上版本可用, |
pexpire | pexpire key-name milliseconds | 讓給定鍵再指定的毫秒之后過期。這個命令在Redis2.6或以上版本可用。 |
pexpireat | pexpireat key-name timestamp-milliseconds | 將一個毫秒級精確的UNIX時間戳設置為給定鍵的過期時間,這個命令在Redis2.6或以上版本可用。 |
下面代碼展示了幾個對鍵執行過期時間操作的例子:
import redis # 導入redis包包 import time # 與本地redis進行鏈接,地址為:localhost,端口號為6379 r = redis.StrictRedis(host="localhost", port=6379) r.delete("trans:") #設置一個簡單的字符串值作為過期時間的設置對象 print(r.set("key","value")) print(r.get("key")) print(r.expire("key",2)) time.sleep(1) #查看鍵距離過期還有多長時間 print(r.ttl("key")) time.sleep(1) #此時鍵已經過期,并被刪除 print(r.get("key"))
運行結果:
True b"value" True 1 None
上一篇文章:Python--Redis實戰:第三章:Redis命令:第六節:發布與訂閱
下一篇文章:Python--Redis實戰:第四章:數據安全與性能保障:第1節:持久化選項
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/44986.html
摘要:為了讓讀者做好使用構建真實軟件的準備,本章將展示維護數據安全以及應對系統故障的方法。上一篇文章實戰第三章命令第七節其他命令下一篇文章實戰第四章數據安全與性能保障第節快照持久化 上一篇文章:Python--Redis實戰:第三章:Redis命令:第七節:其他命令下一篇文章:Python--Redis實戰:第四章:數據安全與性能保障:第2節:快照持久化 前面的幾章介紹了各式各樣的Redi...
摘要:上一篇文章實戰第三章命令第五節有序集合下一篇文章實戰第三章命令第七節其他命令一般來說,發布與訂閱又稱的特點是訂閱者負責訂閱頻道,發送者負責向頻道發送二進制字符串消息。到目前為止,本書介紹的大多數命令都是與特定數據類型相關的。 上一篇文章:Python--Redis實戰:第三章:Redis命令:第五節:有序集合下一篇文章:Python--Redis實戰:第三章:Redis命令:第七節:其...
閱讀 2942·2021-10-28 09:32
閱讀 2967·2021-10-11 10:57
閱讀 3114·2021-10-08 10:05
閱讀 2588·2021-09-28 09:36
閱讀 2213·2019-08-30 15:55
閱讀 2270·2019-08-30 15:44
閱讀 2394·2019-08-30 14:02
閱讀 3076·2019-08-29 17:16