標籤:序列 ann ted 通過 複數 rod 簡潔 重複數 介面
redis是一個開源的使用ANSI C語言編寫、支援網路、可基於記憶體、亦可持久化的日誌型、key-value資料庫,並提供多種語言的API。它是記憶體儲存的資料結構伺服器,可用作資料庫、快取和訊息佇列代理。通過資料全部in-momery的方式保證高速訪問,同時提供資料落地的功能,這是redis最主要的適用情境。reids內建複製、Lua指令碼、LRU收回、事物以及不同層級磁碟持久化功能,同時通過redis Sentinel提供高可用,通過Redis Cluster提供自動分區。redis支援字串、雜湊表、列表、集合、有序集合、位元影像、hyperloglogs等資料類型。redis最為常用的資料類型:string、hash、list、set、sorted set、pub/sub、transactions。String類型string類型就是簡單的key-value類型,value不僅僅是string,也可以是數字。常用命令:set、get、decr、incr、mget等。除了提供與memcached一樣的get、set、incr、decr 等操作外,redis還提供了下面的一些操作:(1)擷取字串長度;(2)往字串append內容;(3)設定和擷取字串的某一段內容;(4)設定及擷取字串的某一位(bit);(5)大量設定一系列字串的內容;Hash類型hash特別適合用於儲存物件。常用命令:hget、hset、hgetall等。應用情境:儲存一些結構化的資料,比如使用者的暱稱、年齡、性別、積分等,儲存一個使用者資訊對象資料。我們舉個簡單的執行個體來描述下Hash的應用情境,比如我們儲存一個使用者資訊對象資料,包含以下資訊:(1)使用者id為尋找的key;(2)儲存的value包括姓名、年齡、生日等資訊1、執行個體解析:(1)key是使用者id,value是一個Map。(2)這個Map的key是成員的屬性名稱,value是屬性值;(3)這樣對資料的修改和存取都可以直接通過其內部的Map的key(redis裡稱內部Map的key為field),也就是key(使用者名稱id)+field(屬性名稱)就可以操作對應屬性資料了。2、注意:(1)redis提供了介面(hgetall)可以直接取到全部的屬性資料,但是如果內部Map的成員很多,那麼涉及到遍曆整個Map的操作。(2)由於redis單執行緒模式的緣故,這個遍曆操作可能會比較耗時,而令其他用戶端的請求完全響應不到,這點需要注意。List類型list類型實質是一個每個元素都是string類型的雙向鏈表,這使得list既可以用作棧,也可以用作隊列。list類型經常會被用於訊息佇列的服務,以完成多程式之間的訊息交換。常用命令:lpush、rpush、lpop、rpop、lrange等。應用情境:實現最新訊息排行等功能,還有訊息佇列。簡單訊息佇列舉例分析:(1)假設一個應用程式執行lpush向鏈表中添加新的元素,我們通常將這樣的程式稱之為“生產者(producer)”;(2)而另外一個應用程式正在執行rpop操作從鏈表中取出元素,我們稱這樣的程式為“消費者(consumer)”;(3)在消費者消費訊息的過程中,需要不停調用rpop查看list中是否有待處理訊息。每調用一次都會發起一次連結,造成不必要的浪費。(4)另外,如果生產者速度大於消費者速度,訊息佇列長度會一直增大,時間久了會佔用大量記憶體空間;(5)所以,可以使用brpop命令,這個命令只有在有元素時返回,沒有則會阻塞直到逾時返回null。Set類型set類型是string類型的無序集合。set集合的概念就是一堆不重複值的組合。set元素最大可以包含(2的32次方-1)個元素。set內部實現是一個value永遠為null的HashMap。set對外提供的功能與list類似是一個列表的功能,特殊之處在於set時可以自動排重的。常用命令:sadd、spop、smembers、sunion等。當你需要儲存一個列表資料,又不希望出現重複資料時,set是一個很好的選擇。並且set提供了判斷某個成員是否在一個set集合內的重要介面,這個是list不能提供的。利用set資料結構,可以儲存一些集合性的資料,比如在微博應用中,可以將一個使用者所有的關注人存在一個集合中,將其所有粉絲存在一個集合。redis還為集合提供了求交集、並集、差集等操作,可以非常方便的實現如共同關注、共同喜好、二度好友等功能。Zset類型和set一樣,sorted set也是stirng類型元素的集合。不同的是每個元素都會關聯一個double類型的score,元素順序由score決定。sorted set是插入有序的,即自動排序。常用命令:zadd、zrange、zrem、zcard等。當你需要一個有序的並且不重複的集合列表時,那麼可以選擇sorted set資料結構。應用舉例:(1)例如儲存全班同學的成績,其集合value可以是同學的學號,而score就可以是成績。(2)熱門排行榜應用,根據得分列出topN的使用者等。pub/subsubscribe、unsubscribe和publish三個命令實現了發布與訂閱泛型。寄件者(發送資訊的用戶端)不是直接將資訊發給特定的接收者(接受資訊的用戶端),而是將資訊發給頻道(channel),然後由頻道將資訊轉寄給所有對這個頻道感興趣的訂閱者。寄件者無需知道任何關於訂閱者的資訊,而訂閱者也無需知道是哪個用戶端給它發送資訊,它只要關注自己感興趣的頻道即可。發布/訂閱在redis中,被設計的非常輕量級和簡潔,它做到了訊息的發布和訂閱的基本能力;但是尚未提供關於訊息持久化等各種企業級的特性。一個redis client發布訊息,其他多個redis client訂閱訊息,發布的訊息即發即失,redis不會持久儲存發布的訊息;訊息訂閱者也只能得到訂閱後的訊息,通道中此前的訊息無從獲得。訊息發行者,即publish用戶端,無需獨佔連結,你可以在publish訊息的同時,使用同一個redis-client連結進行其他動作(如incr等);訊息訂閱者,即subscribe用戶端,需要獨佔連結,即進行subscribe期間,redis-client無法穿插其他動作。此時client以阻塞的方式等待publish端的訊息,因此subscribe需要使用單獨的連結,甚至需要在額外的線程中使用。tcp預設連線時間固定,如果在這世間內sub端沒有接收到pub端訊息,或pub端沒有訊息產生,sub端的串連都會強制回收。這就需要特殊手段解決,用定時器來類比pub和sub之間的保活機制,定時器時間不能超過tcp最大連線時間。一旦subscribe端取消連結,將會失去部分訊息,即連結失效期間的訊息將會被丟失,所以,這裡需要考慮redis的list來持久化;如果你非常關注每個訊息,那麼你應該基於redis做一些額外的補充工作,如果你希望訂閱是持久的,那麼如下設計思路可以借鑒:(1)subscribe端:首先向一個set集合中增加“訂閱者id”,此set集合儲存了“活躍訂閱”者;訂閱者id標記每個唯一的訂閱者,此set為“活躍訂閱者集合”。(2)subscribe端開啟訂閱操作,並基於redis建立一個以訂閱者id為key的list資料結構,此list中儲存了所有的尚未消費的訊息,此list稱為“訂閱者訊息佇列”;(3)publish端:每發布一條訊息之後,publish端都需要遍曆活躍訂閱者集合,並依次向每個“訂閱者訊息佇列”尾部追加此次發布的訊息;(4)到此為止,我們基本可以保證,發布的每一條訊息,都會持久的儲存在每個“訂閱者訊息佇列”中;(5)subscribe端,每接收到一個訂閱訊息,在消費周后,必須刪除自己的“訂閱者訊息佇列”頭部的一條訊息;(6)subscribe端啟動時,如果發現自己的“訂閱者訊息佇列”中有殘存記錄,那麼將會首先消費這些訊息,然後再去訂閱。以上方法可以保證成功到達的訊息必消費不丟失transactionsredis事務可以一次執行多個命令。一個事務從開始到執行會經曆三個階段:(1)開始事務(2)命令入隊(3)執行事務事務是一個單獨的隔離操作:事務中的所有命令都會序列化、按順序執行。事務在執行的過程中,不會被其他用戶端發送來的命令請求所打斷。單個redis命令的執行時原子性的,但redis沒有在事務上增加任何維持原子性的機制,所以redis事務的執行並不是原子性的。事務可以理解為一個打包的批量執行指令碼,但批量指令並非原子化的操作,中間某條指令的失敗不會導致前面已做指令的復原,也不會造成後續的指令不做。multi、exec、discard和watch命令是redis事務的基礎。multi:(1)multi命令用於開啟一個事務,它總是返回ok。(2)multi命令執行之後,用戶端可以繼續向伺服器發送任意多條命令;(3)這些命令不會立即被執行,而是被放到一個隊列中;(4)當exec命令被調用時,所有隊列中的命令才會被執行。exec:(1)exec命令負責觸發並執行事務中的所有命令;(2)如果用戶端在使用multi開啟了一個事務後,卻因為斷線而沒有成功執行exec命令,那麼事務中所有的命令都不會被執行。(3)另一方面,如果用戶端成功在開啟事務之後執行exec命令,那麼事務中的所有命令都會被執行。discard:(1)通過調用discard,用戶端可以清空事務隊列,並放棄執行事務。watch:(1)watch命令可以為redis事務提供check-and-set (CAS)行為。 (2)watch使得exec命令有條件的執行:事務只能在所有被監控健都沒有被修改的前提下執行,如果這個前提不能滿足,事務就不會執行。(3)如果你用watch監視來一個帶到期時間的健,那麼即使這個健到期了,事務仍然可以執行。(4)watch可以被調用多次,對健的監視從watch被執行之後就生效,直到調用exec為止。(5)當exec被調用時,不管事務是否被成功執行,對所有健的監視都會被取消。(6)當用戶端取消連結時,該用戶端對健的監視也會被取消。
redis 資料類型