redis五種數據類型和經常使用命令及適用場景

一.redis的5種數據類型:

1.基礎理解:
string 字符串(能夠爲整形、浮點型和字符串,統稱爲元素)
list 列表(實現隊列,元素不惟一,先入先出原則)
set 集合(各不相同的元素)
hash hash散列值(hash的key必須是惟一的)
sort set 有序集合
html

2.全部命令:http://redisdoc.com/web

——————————————————————————————————————————————————————————————————————————————————————————————————redis

二.命令

(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的位置;vim

(2).list:
列表類型(list)用於存儲一個有序的字符串列表,經常使用的操做是向隊列兩端添加元素或者得到列表的某一片斷。列表內部使用的是雙向鏈表(double linked list)實現的,因此向列表兩端添加元素的時間複雜度是O(1),獲取越接近列表兩端的元素的速度越快。可是缺點是使用列表經過索引訪問元素的效率過低(須要從端點開始遍歷元素)。因此列表的使用場景通常如:朋友圈新鮮事,只關心最新的一些內容。藉助列表類型,Redis還能夠做爲消息隊列使用。api

查詢:
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,以離表頭最近的爲準ruby

刪除:
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個字段。

  1. HDEL key field [field2] 刪除一個或多個哈希表字段

  2. HEXISTS key field 查看哈希表 key 中,指定的字段是否存在, 返回0 || 1

  3. HGET key field 獲取存儲在哈希表中指定字段的值

  4. HGETALL key 獲取在哈希表中指定 key 的全部字段和值

  5. HINCRBY key field increment 爲哈希表 key 中的指定字段的整數值加上增量 increment

  6. HINCRBYFLOAT key field increment 爲哈希表 key 中的指定字段的浮點數值加上增量 increment

  7. HKEYS key 獲取全部哈希表中的字段

  8. HLEN key 獲取哈希表中字段的數量

  9. HMGET key field1 [field2] 獲取全部給定字段的值

  10. HMSET key field1 value1 [ field2 value2 ]同時將多個 field-value (域-值)對設置到哈希表 key 中

  11. HSET key field value將哈希表 key 中的字段 field 的值設爲 value

  12. HSETNX key field value只有在字段 field 不存在時,設置哈希表字段的值

  13. HVALS key 獲取哈希表中全部值

  14. 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
redis-cli -h 10.132.3.213 -p 6379 -a 888k6 -n 4 keys 「ecard
」 | xargs redis-cli -h 10.132.3.213 -p 6379 -a 888k6 -n 4 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

相關文章
相關標籤/搜索