redis五種資料型別和常用命令及適用場景
一.redis的5種資料型別: 1.基礎理解: string 字串(可以為整形、浮點型和字串,統稱為元素) list 列表(實現佇列,元素不唯一,先入先出原則) set 集合(各不相同的元素) hash hash雜湊值(hash的key必須是唯一的) sort set 有序集合
2.所有命令:http://redisdoc.com/
二.命令 (1).string型別的常用命令:它能夠儲存任何型別的字串,包含二進位制資料。可以用於儲存郵箱,JSON化的物件,甚至是一張圖片,一個字串允許儲存的最大容量為512MB。 SET key value SET 賦值; SETNX key value 如果key不存在則賦值,如果key存在不賦值; SETEX key timeout value 設定KEY的過期時間 GET key GET 取值; INCR key INCR 遞增數字,僅僅對數字型別的鍵有用,相當於Java的i++運算; INCRBY key increment INCRBY 增加指定的數字,僅僅對數字型別的鍵有用,相當於Java的i+=3,increment可以為負數,表示減少; DECR key DECR 遞減數字,僅僅對數字型別的鍵有用,相當於Java的i––; DECRBY key decrement DECRBY 減少指定的數字,僅僅對數字型別的鍵有用,相當於Java的i-=3,decrement可以為正數,表示增加; INCRBYFLOAT key increment INCRBYFLOAT 增加指定浮點數,僅僅對數字型別的鍵有用; APPEND key value APPEND 向尾部追加值,相當於Java中的”hello”.append(“ world”); STRLEN key STRLEN 獲取字串長度; MSET key1 value1 [key2 value2 ...] MSET 同時設定多個key的值; MGET key1 [key2 ...] MGET 同時獲取多個key的值;
位操作 GETBIT key offset GETBIT獲取一個鍵值的二進位制位的指定位置的值(0/1); SETBIT key offset value SETBIT設定一個鍵值的二進位制位的指定位置的值(0/1); BITCOUNT key [start end] BITCOUNT 獲取一個鍵值的一個範圍內的二進位制表示的1的個數; BITOP OP desKey key1 key2 BITOP 該命令可以對多個字串型別鍵進行位運算,並將結果儲存到指定的鍵中,BITOP支援的運算包含:OR,AND,XOR,NOT; BITPOS key 0/1 [start, end] BITPOS 獲取指定鍵的第一個位值為0或者1的位置;
(2).list: 列表型別(list)用於儲存一個有序的字串列表,常用的操作是向佇列兩端新增元素或者獲得列表的某一片段。列表內部使用的是雙向連結串列(double linked list)實現的,所以向列表兩端新增元素的時間複雜度是O(1),獲取越接近列表兩端的元素的速度越快。但是缺點是使用列表通過索引訪問元素的效率太低(需要從端點開始遍歷元素)。所以列表的使用場景一般如:朋友圈新鮮事,只關心最新的一些內容。藉助列表型別,Redis還可以作為訊息佇列使用。
查詢: 1.lindex [lindex key index]:通過索引index獲取列表的元素、key>=0從頭到尾,key<0從尾到頭 2.lrange [lrange key range_l range_r]:0 表頭、-1表尾
增加: 1.lpush [lpush key valus...] 類似於壓棧操作,將元素放入頭部 2.lpushx [lpushx key valus]:只能插入已經存在的key,且一次只能插入一次 3.rpush [rpush key valus...] :將元素push在list的尾部 4.rpushx [rpushx key valus...] :相對於lpushx 5.linsert [linsert key before/after pivot value]:將值插入到pivot的前面或後面。返回列表元素個數。如果參照點pivot不存在不插入。如果有多個pivot,以離表頭最近的為準
刪除: 1.lpop 、rpop:分別為刪除頭部和尾部,返回被刪除的元素 2.ltrim [ltrim key range_l range_r]:保留區域類的元素,其他的刪除 3.lrem [lrem key count value] :移除等於value的元素,當count>0時,從表頭開始查詢,移除count個;當count=0時,從表頭開始查詢,移除所有等於value的;當count<0時,從表尾開始查詢,移除|count| 個
修改: 1.lset [lset key index value] : 設定列表指定索引的值,如果指定索引不存在則報錯
RPOPLPUSH source destination 將元素從一個列表轉義到另一個列表;
(3).set型別支援的常用命令:集合在概念在高中課本就學過,集合中每個元素都是不同的,集合中的元素個數最多為2的32次方-1個,集合中的元素是沒有順序的。 SADD key value1 [value2 value3 ...] 新增元素; SREM key value2 [value2 value3 ...] 刪除元素; SMEMBERS key 獲得集合中所有元素; SISMEMBER key value 判斷元素是否在集合中; SDIFF key1 key2 [key3 ...] 對集合做差集運算,先計算key1和key2的差集,然後再用結果與key3做差集; SINTER key1 key2 [key3 ...] 對集合做交集運算; SUNION key1 key2 [key3 ...] 對集合做並集運算; SCARD key 獲得集合中元素的個數; SPOP key 從集合中隨機彈出一個元素; SDIFFSTORE destination key1 key2 [key3 ...] 對集合做差集並將結果儲存在destination; SINTERSTORE destination key1 key2 [key3 ...] 對集合做交集運算並將結果儲存在destination; SUNIONSTORE destination key1 key2 [key3 ...] 對集合做並集運算並將結果儲存在destination; SRANDMEMBER key [count] 隨機獲取集合中的元素,當count>0時,會隨機中集合中獲取count個不重複的元素,當count<0時,隨機中集合中獲取|count|和可能重複的元素。 SMOVE source destination member 將 member 元素從 source 集合移動到 destination 集合
(4).hash資料型別支援的常用命令: 雜湊型別相當於Java中的HashMap,他的值是一個字典,儲存很多key,value對,每對key,value的值個鍵都是字串型別,換句話說,雜湊型別不能巢狀其他資料型別。一個雜湊型別鍵最多可以包含2的32次方-1個欄位。
HDEL key field [field2] 刪除一個或多個雜湊表字段
HEXISTS key field 檢視雜湊表 key 中,指定的欄位是否存在, 返回0 || 1
HGET key field 獲取儲存在雜湊表中指定欄位的值
HGETALL key 獲取在雜湊表中指定 key 的所有欄位和值
HINCRBY key field increment 為雜湊表 key 中的指定欄位的整數值加上增量 increment
HINCRBYFLOAT key field increment 為雜湊表 key 中的指定欄位的浮點數值加上增量 increment
HKEYS key 獲取所有雜湊表中的欄位
HLEN key 獲取雜湊表中欄位的數量
HMGET key field1 [field2] 獲取所有給定欄位的值
HMSET key field1 value1 [ field2 value2 ]同時將多個 field-value (域-值)對設定到雜湊表 key 中
HSET key field value將雜湊表 key 中的欄位 field 的值設為 value
HSETNX key field value只有在欄位 field 不存在時,設定雜湊表字段的值
HVALS key 獲取雜湊表中所有值
HSCAN key cursor [MATCH pattern] [COUNT count] 迭代雜湊表中的鍵值對
(5).sort set:有序集合型別與集合型別的區別就是他是有序的。有序集合是在集合的基礎上為每一個元素關聯一個分數,這就讓有序集合不僅支援插入,刪除,判斷元素是否存在等操作外,還支援獲取分數最高/最低的前N個元素。有序集合中的每個元素是不同的,但是分數卻可以相同。有序集合使用散列表和跳躍表實現,即使讀取位於中間部分的資料也很快,時間複雜度為O(log(N)),有序集合比列表更費記憶體。 ZADD key score1 value1 [score2 value2 score3 value3 ...] 新增元素; ZSCORE key value 獲取元素的分數; ZRANGE key start stop [WITHSCORE] 獲取排名在某個範圍的元素,按照元素從小到大的順序排序,從0開始編號,包含start和stop對應的元素,WITHSCORE選項表示是否返回元素分數; ZREVRANGE key start stop [WITHSCORE] 獲取排名在某個範圍的元素,和上一個命令用法一樣,只是這個倒序排序的; ZRANGEBYSCORE key min max 獲取指定分數範圍內的元素,包含min和max,(min表示不包含min,(max表示不包含max,+inf表示無窮大; ZINCRBY key increment value 增加某個元素的分數; ZCARD key 獲取集合中元素的個數; ZCOUNT key min max 返回有序集 key 中, score 值在 min 和 max 之間(預設包括 score 值等於 min 或 max )的成員的數量 ZREM key value1 [value2 ...] 刪除一個或多個元素; ZREMRANGEBYRANK key start stop 按照排名範圍刪除元素; ZREMRANGEBYSCORE key min max 按照分數範圍刪除元素; ZRANK key value 獲取正序排序的元素的排名; ZREVRANK key value 獲取逆序排序的元素的排名; ZINTERSTORE destination numbers key1 key2 [key3 key4 ...] WEIGHTS weight1 weight2 [weight3 weight4 ...] AGGREGATE SUM | MIN | MAX 計算有序集合的交集並存儲結果,numbers表示參加運算的集合個數,weight表示權重,aggregate表示結果取值; ZUNIONSTORE 計算有序幾個的並集並存儲結果,用法和上面一樣;
zadd的理解: 將一個或多個 member 元素及其 score 值加入到有序集 key 當中。如果某個 member 已經是有序集的成員,那麼更新這個 member 的 score 值,並通過重新插入這個 member 元素,來保證該 member 在正確的位置上。score 值可以是整數值或雙精度浮點數。如果 key 不存在,則建立一個空的有序集並執行 ZADD 操作。當 key 存在但不是有序集型別時,返回一個錯誤。
(6).其他常用命令: 1.Redis刪除某個資料庫中以某個字元開頭的key redis-cli -n 9 keys "c_recom*" | xargs redis-cli -n 9 del
2.鍵值相關命令 type key 檢視key型別 keys * 檢視所有key exists key 檢視是否有這個key del key 刪除key expire key 100 設定key100秒生存期 ttl key 獲取key的有效時長 [-1存在未設定 -2不存在] ,返回 key 的剩餘生存時間 select 0 選擇到0資料庫 [ redis預設的資料庫是0~15一共16個數據庫 ] move key 1 將當前資料庫中的key移動到其他的資料庫[ 資料庫1 ] persist key 移除key的過期時間 randomkey 隨機返回資料庫裡面的一個key rename key2 key3 重新命名key2 為key3
3.伺服器相關命令 ping PONG 返回響應是否連線成功 echo 在命令列列印一些內容 select 0~15 編號的資料庫 quit || exit 退出客戶端 dbsize 返回當前資料庫中所有key的數量 info 返回redis的相關資訊 config get dir/* 實時傳儲收到的請求 flushdb 刪除當前選擇資料庫中的所有key flushall 刪除所有資料庫中的資料庫
4.info http://redisdoc.com/server/info.html memory相關: used_memory : 由 Redis 分配器分配的記憶體總量,以位元組(byte)為單位 used_memory_human : 以人類可讀的格式返回 Redis 分配的記憶體總量 used_memory_rss : 從作業系統的角度,返回 Redis 已分配的記憶體總量(俗稱常駐集大小)。這個值和 top 、 ps 等命令的輸出一致。 used_memory_peak : Redis 的記憶體消耗峰值(以位元組為單位) used_memory_peak_human : 以人類可讀的格式返回 Redis 的記憶體消耗峰值 used_memory_lua : Lua 引擎所使用的記憶體大小(以位元組為單位) mem_fragmentation_ratio : used_memory_rss 和 used_memory 之間的比率 mem_allocator : 在編譯時指定的, Redis 所使用的記憶體分配器。可以是 libc 、 jemalloc 或者 tcmalloc 。 在理想情況下, used_memory_rss 的值應該只比 used_memory 稍微高一點兒。 當 rss > used ,且兩者的值相差較大時,表示存在(內部或外部的)記憶體碎片。 記憶體碎片的比率可以通過 mem_fragmentation_ratio 的值看出。 當 used > rss 時,表示 Redis 的部分記憶體被作業系統換出到交換空間了,在這種情況下,操作可能會產生明顯的延遲。 Because Redis does not have control over how its allocations are mapped to memory pages, high used_memory_rss is often the result of a spike in memory usage. 當 Redis 釋放記憶體時,分配器可能會,也可能不會,將記憶體返還給作業系統。 如果 Redis 釋放了記憶體,卻沒有將記憶體返還給作業系統,那麼 used_memory 的值可能和作業系統顯示的 Redis 記憶體佔用並不一致。 檢視 used_memory_peak 的值可以驗證這種情況是否發生。
5啟動&關閉 啟動 /usr/local/Cellar/redis/3.2.5/bin/redis-server /usr/local/etc/redis.conf [ redis-server /usr/local/etc/redis.conf ] redis指定配置檔案啟動 vim /usr/local/etc/redis.conf daemonize no(預設),改成 yes,意思是是否要後臺啟動。
關閉 不能用 kill 暴力關閉,因為可能會丟失資料, 使用./redis-cli shutdown,redis 會先儲存好資料,再關閉
三.使用場景 String String資料結構是簡單的key-value型別,value其實不僅可以是String,也可以是數字。 常規key-value快取應用; 常規計數:微博數,粉絲數等。
hash Redis hash是一個string型別的field和value的對映表,hash特別適合用於儲存物件。 儲存部分變更的資料,如使用者資訊等。
list list就是連結串列,略有資料結構知識的人都應該能理解其結構。使用Lists結構,我們可以輕鬆地實現最新訊息排行等功能。List的另一個應用就是訊息佇列,可以利用List的PUSH操作,將任務存在List中,然後工作執行緒再用POP操作將任務取出進行執行。Redis還提供了操作List中某一段的api,你可以直接查詢,刪除List中某一段的元素。 Redis的list是每個子元素都是String型別的雙向連結串列,可以通過push和pop操作從列表的頭部或者尾部新增或者刪除元素,這樣List即可以作為棧,也可以作為佇列。
訊息佇列系統 使用list可以構建佇列系統,使用sorted set甚至可以構建有優先順序的佇列系統。 比如:將Redis用作日誌收集器 實際上還是一個佇列,多個端點將日誌資訊寫入Redis,然後一個worker統一將所有日誌寫到磁碟。
取最新N個數據的操作
//把當前登入人新增到連結串列裡 ret = r.lpush("login:last_login_times", uid) //保持連結串列只有N位 ret = redis.ltrim("login:last_login_times", 0, N-1) //獲得前N個最新登陸的使用者Id列表 last_login_list = r.lrange("login:last_login_times", 0, N-1)
比如sina微博: 在Redis中我們的最新微博ID使用了常駐快取,這是一直更新的。但是做了限制不能超過5000個ID,因此獲取ID的函式會一直詢問Redis。只有在start/count引數超出了這個範圍的時候,才需要去訪問資料庫。 系統不會像傳統方式那樣“重新整理”快取,Redis例項中的資訊永遠是一致的。SQL資料庫(或是硬碟上的其他型別資料庫)只是在使用者需要獲取“很遠”的資料時才會被觸發,而主頁或第一個評論頁是不會麻煩到硬碟上的資料庫了。
set set就是一個集合,集合的概念就是一堆不重複值的組合。利用Redis提供的set資料結構,可以儲存一些集合性的資料。set中的元素是沒有順序的。 案例: 在微博應用中,可以將一個使用者所有的關注人存在一個集合中,將其所有粉絲存在一個集合。Redis還為集合提供了求交集、並集、差集等操作,可以非常方便的實現如共同關注、共同喜好、二度好友等功能,對上面的所有集合操作,你還可以使用不同的命令選擇將結果返回給客戶端還是存集到一個新的集合中。
交集,並集,差集
//book表儲存book名稱 set book:1:name "The Ruby Programming Language" set book:2:name "Ruby on rail" set book:3:name "Programming Erlang"
//tag表使用集合來儲存資料,因為集合擅長求交集、並集 sadd tag:ruby 1 sadd tag:ruby 2 sadd tag:web 2 sadd tag:erlang 3
//即屬於ruby又屬於web的書? inter_list = redis.sinter("tag:web", "tag:ruby") //即屬於ruby,但不屬於web的書? diff_list = redis.sdiff("tag:ruby", "tag:web") //屬於ruby和屬於web的書的合集? union_list = redis.sunion("tag:ruby", "tag:web")
獲取某段時間所有資料去重值 這個使用Redis的set資料結構最合適了,只需要不斷地將資料往set中扔就行了,set意為集合,所以會自動排重。
sorted set 和set相比,sorted set增加了一個權重引數score,使得集合中的元素能夠按score進行有序排列,比如一個儲存全班同學成績的sorted set,其集合value可以是同學的學號,而score就可以是其考試得分,這樣在資料插入集合的時候,就已經進行了天然的排序。可以用sorted set來做帶權重的佇列,比如普通訊息的score為1,重要訊息的score為2,然後工作執行緒可以選擇按score的倒序來獲取工作任務。讓重要的任務優先執行。
排行榜應用,取TOP N操作 這個需求與上面需求的不同之處在於,前面操作以時間為權重,這個是以某個條件為權重,比如按頂的次數排序,這時候就需要我們的sorted set出馬了,將你要排序的值設定成sorted set的score,將具體的資料設定成相應的value,每次只需要執行一條ZADD命令即可。
//將登入次數和使用者統一儲存在一個sorted set裡 zadd login:login_times 5 1 zadd login:login_times 1 2 zadd login:login_times 2 3
//當用戶登入時,對該使用者的登入次數自增1 ret = r.zincrby("login:login_times", 1, uid) //那麼如何獲得登入次數最多的使用者呢,逆序排列取得排名前N的使用者 ret = r.zrevrange("login:login_times", 0, N-1) 比如線上遊戲的排行榜,根據得分你通常想要:
- 列出前100名高分選手
- 列出某使用者當前的全球排名
這些操作對於Redis來說小菜一碟,即使你有幾百萬個使用者,每分鐘都會有幾百萬個新的得分。 模式是這樣的,每次獲得新得分時,我們用這樣的程式碼:
ZADD leaderboard
你可能用userID來取代username,這取決於你是怎麼設計的。 得到前100名高分使用者很簡單:
ZREVRANGE leaderboard 0 99
使用者的全球排名也相似,只需要:
ZRANK leaderboard
需要精準設定過期時間的應用 比如你可以把上面說到的sorted set的score值設定成過期時間的時間戳,那麼就可以簡單地通過過期時間排序,定時清除過期資料了,不僅是清除Redis中的過期資料,你完全可以把Redis裡這個過期時間當成是對資料庫中資料的索引,用Redis來找出哪些資料需要過期刪除,然後再精準地從資料庫中刪除相應的記錄。
範圍查詢 來自Redis在Google Group上的一個問題,有一位同學發貼求助,說要解決如下的一個問題:他有一個IP範圍對應地址的列表,現在需要給出一個IP的情況下,迅速的查詢到這個IP在哪個範圍,也就是要判斷此IP的所有地。這個問題引來了Redis作者Salvatore Sanfilippo(@antirez)的回答。解答如下: 例如有下面兩個範圍,10-20和30-40
- A_start 10, A_end 20
- B_start 30, B_end 40 我們將這兩個範圍的起始位置存在Redis的sorted set資料結構中,基本範圍起始值作為score,範圍名加start和end為其value值:
redis 127.0.0.1:6379> zadd ranges 10 A_start
redis 127.0.0.1:6379> zadd ranges 20 A_end
redis 127.0.0.1:6379> zadd ranges 30 B_start
redis 127.0.0.1:6379> zadd ranges 40 B_end
這樣資料在插入sorted set後,相當於是將這些起始位置按順序排列好了。 現在我需要查詢15這個值在哪一個範圍中,只需要進行如下的zrangbyscore查詢:
redis 127.0.0.1:6379> zrangebyscore ranges (15 +inf LIMIT 0 1
這個命令的意思是在Sorted Sets中查詢大於15的第一個值。(+inf在Redis中表示正無窮大,15前面的括號表示>15而非>=15) 查詢的結果是A_end,由於所有值是按順序排列的,所以可以判定15是在A_start到A_end區間上,也就是說15是在A這個範圍裡。至此大功告成。 當然,如果你查詢到的是一個start,比如咱們用25,執行下面的命令:
redis 127.0.0.1:6379> zrangebyscore ranges (25 +inf LIMIT 0 1
返回結果表明其下一個節點是一個start節點,也就是說25這個值不處在任何start和end之間,不屬於任何範圍。 當然,這個例子僅適用於類似上面的IP範圍查詢的案例,因為這些值範圍之間沒有重合。如果是有重合的情況,這個問題本身也就變成了一個一對多的問題。
Pub/Sub Pub/Sub 從字面上理解就是釋出(Publish)與訂閱(Subscribe),在Redis中,你可以設定對某一個key值進行訊息釋出及訊息訂閱,當一個key值上進行了訊息釋出後,所有訂閱它的客戶端都會收到相應的訊息。這一功能最明顯的用法就是用作實時訊息系統,比如普通的即時聊天,群聊等功能。
使用場景
Pub/Sub構建實時訊息系統
Redis的Pub/Sub系統可以構建實時的訊息系統 比如很多用Pub/Sub構建的實時聊天系統的例子。
參考: 深入淺出redis底層資料結構系列 https://www.cnblogs.com/jaycekon/p/6227442.html(上) https://www.cnblogs.com/jaycekon/p/6277653.html(下)
http://www.redis.net.cn/tutorial/3501.html http://www.cnblogs.com/markhe/p/5689356.html http://www.cnblogs.com/ggjucheng/p/3349102.html https://blog.csdn.net/Richard_Jason/article/details/53130369