1、Redis介紹
Redis是一個開源的使用ANSI C語言編寫、支持網絡、可基於內存亦可持久化的日誌型、Key-Value數據庫,並提供多種語言的API。從2010年3月15日起,Redis的開發工做由VMware主持。redis
Redis能運行在大多數POSIX(Linux, *BSD, OS X 和Solaris等)系統上,官方沒有支持Windows的版本。目前最新的版本是2.2.11,這個版本主要是修復了一個2.2.7版本中遍歷方式優化帶來的一個bug。
和普通的Key-Value結構不一樣,Redis的Key支持靈活的數據結構,除了strings,還有hashes、lists、 sets 和sorted sets等結構。正是這些靈活的數據結構,豐富了Redis的應用場景,能知足更多業務上的靈活存儲需求。
Redis的數據都保存在內存中,並且底層實現上是本身寫了epoll event loop部分,而沒有采用開源的libevent等通用框架,因此讀寫效率很高。爲了實現數據的持久化,Redis支持按期刷新(可經過配置實現)或寫日誌的方式來保存數據到磁盤。數據庫
一、數據類型
做爲Key-value型數據庫,Redis也提供了鍵(Key)和鍵值(Value)的映射關係。可是,除了常規的數值或字符串,Redis的鍵值還能夠是如下形式之一:
●Lists (列表)
●Sets (集合)
●Sorted sets (有序集合)
●Hashes (哈希表)
鍵值的數據類型決定了該鍵值支持的操做。Redis支持諸如列表、集合或有序集合的交集、並集、查集等高級原子操做;同時,若是鍵值的類型是普通數字,Redis則提供自增等原子操做。c#
二、持久化
一般,Redis將數據存儲於內存中,或被配置爲使用虛擬內存。經過兩種方式能夠實現數據持久化:使用截圖的方式,將內存中的數據不斷寫入磁盤;或使用相似MySQL的日誌方式,記錄每次更新的日誌。前者性能較高,可是可能會引發必定程度的數據丟失;後者相反。數組
三、主從同步
Redis支持將數據同步到多臺從庫上,這種特性對提升讀取性能很是有益。緩存
四、性能
相比須要依賴磁盤記錄每一個更新的數據庫,基於內存的特性無疑給Redis帶來了很是優秀的性能。讀寫操做之間有顯著的性能差別。安全
五、提供API的語言
●C
●C++
●C#
●Clojure
●Common Lisp
●Erlang
●Haskell
●Java
●Javascript
●Lua
●Objective-C
●Perl
●PHP
●Python
●Ruby
●Scala
●Go
●Tcl服務器
六、適用場合
毫無疑問,Redis開創了一種新的數據存儲思路,使用Redis,咱們不用在面對功能單調的數據庫時,把精力放在如何把大象放進冰箱這樣的問題上,而是利用Redis靈活多變的數據結構和數據操做,爲不一樣的大象構建不一樣的冰箱。但願你喜歡這個比喻。
下面是Redis適用的一些場景:
(1)、取最新N個數據的操做
好比典型的取你網站的最新文章,經過下面方式,咱們能夠將最新的5000條評論的ID放在Redis的List集合中,並將超出集合部分從數據庫獲取。
使用LPUSH latest.comments命令,向list集合中插入數據
插入完成後再用LTRIM latest.comments 0 5000命令使其永遠只保存最近5000個ID
而後咱們在客戶端獲取某一頁評論時能夠用下面的邏輯
FUNCTION get_latest_comments(start,num_items):
id_list = redis.lrange(「latest.comments」,start,start+num_items-1)
IF id_list.length < num_items
id_list = SQL_DB(「SELECT … ORDER BY time LIMIT …」)
END
RETURN id_list
END
若是你還有不一樣的篩選維度,好比某個分類的最新N條,那麼你能夠再建一個按此分類的List,只存ID的話,Redis是很是高效的。
(2)、排行榜應用,取TOP N操做
這個需求與上面需求的不一樣之處在於,前面操做以時間爲權重,這個是以某個條件爲權重,好比按頂的次數排序,這時候就須要咱們的sorted set出馬了,將你要排序的值設置成sorted set的score,將具體的數據設置成相應的value,每次只須要執行一條ZADD命令便可。
(3)、須要精準設定過時時間的應用
好比你能夠把上面說到的sorted set的score值設置成過時時間的時間戳,那麼就能夠簡單地經過過時時間排序,定時清除過時數據了,不只是清除Redis中的過時數據,你徹底能夠把Redis裏這個過時時間當成是對數據庫中數據的索引,用Redis來找出哪些數據須要過時刪除,而後再精準地從數據庫中刪除相應的記錄。
(4)、計數器應用
Redis的命令都是原子性的,你能夠輕鬆地利用INCR,DECR命令來構建計數器系統。
(5)、Uniq操做,獲取某段時間全部數據排重值
這個使用Redis的set數據結構最合適了,只須要不斷地將數據往set中扔就好了,set意爲集合,因此會自動排重。
(6)、實時系統,反垃圾系統
經過上面說到的set功能,你能夠知道一個終端用戶是否進行了某個操做,能夠找到其操做的集合並進行分析統計對比等。沒有作不到,只有想不到。
(7)、Pub/Sub構建實時消息系統
Redis的Pub/Sub系統能夠構建實時的消息系統,好比不少用Pub/Sub構建的實時聊天系統的例子。
(8)、構建隊列系統
使用list能夠構建隊列系統,使用sorted set甚至能夠構建有優先級的隊列系統。
(9)、緩存
這個沒必要說了,性能優於Memcached,數據結構更多樣化。網絡
2、安裝及使用
步驟一: 下載Redis
下載安裝包:wget http://download.redis.io/releases/redis-3.0.6.tar.gz
[root@localhost 4setup]# wget http://download.redis.io/releases/redis-3.0.6.tar.gz
步驟二: 編譯源程序
[root@localhost 4setup]# ll
[root@localhost 4setup]# tar xzf redis-3.0.6.tar.gz
[root@localhost 4setup]# cd redis-3.0.6
[root@localhost redis-2.2.12]# make
cd src && make all
make[1]: Entering directory `/root/4setup/redis-3.0.6/src’
步驟三: 啓動Redis服務
src/redis-server
[root@localhost redis-2.2.12]# src/redis-server
Redis 服務端的默認鏈接端口是 6379。
使用指定配置文件啓動
src/redis-server redis.conf
步驟四: 將Redis做爲 Linux 服務隨機啓動
vi /etc/rc.local, 使用vi編輯器打開隨機啓動配置文件,並在其中加入下面一行代碼。
/root/4setup/redis-3.0.6/src/redis-server
步驟五: 客戶端鏈接驗證
新打開一個Session輸入:src/redis-cli,若是出現下面提示,那麼您就能夠開始Redis之旅了。
[root@localhost redis-3.0.6]# src/redis-cli
redis 127.0.0.1:6379>
步驟六: 查看Redis日誌
查看服務器端session,便可對Redis的運行情況進行查看或分析了。
[6246] 05 Aug 19:24:33 – 0 clients connected (0 slaves), 539544 bytes in use
[6246] 05 Aug 19:24:37 – Accepted 127.0.0.1:51381
[6246] 05 Aug 19:24:38 – 1 clients connected (0 slaves), 547372 bytes in use
以上的幾個步驟就OK了!!這樣一個簡單的Redis數據庫就能夠暢通無阻地運行起來了。
步驟七: 中止Redis實例
最簡單的方法是在啓動實例的session中,直接使用Control-C來將實例中止。
咱們還能夠用客戶端來中止服務,如能夠用shutdown來中止Redis實例, 具體以下:
[root@localhost redis-3.0.6]# src/redis-cli shutdownsession
3、配置Redis
使用配置文件啓動:src/redis-server redis.conf
主要配置項:
Redis支持不少的參數,但都有默認值。
●daemonize:
默認狀況下,redis不是在後臺運行的,若是須要在後臺運行,把該項的值更改成yes。
●pidfile
當Redis在後臺運行的時候,Redis默認會把pid文件放在/var/run/redis.pid,你能夠配置到其餘地址。當運行多個redis服務時,須要指定不一樣的pid文件和端口。
●bind
指定Redis只接收來自於該IP地址的請求,若是不進行設置,那麼將處理全部請求,在生產環境中最好設置該項。
●port
監聽端口,默認爲6379。
●timeout
設置客戶端鏈接時的超時時間,單位爲秒。當客戶端在這段時間內沒有發出任何指令,那麼關閉該鏈接。
●loglevel
log等級分爲4級,debug, verbose, notice, 和warning。生產環境下通常開啓notice。
●logfile
配置log文件地址,默認使用標準輸出,即打印在命令行終端的窗口上。
●databases
設置數據庫的個數,可使用SELECT 命令來切換數據庫。默認使用的數據庫是0。
●save
設置Redis進行數據庫鏡像的頻率。
if(在60秒以內有10000個keys發生變化時){
進行鏡像備份
}else if(在300秒以內有10個keys發生了變化){
進行鏡像備份
}else if(在900秒以內有1個keys發生了變化){
進行鏡像備份
}
●rdbcompression
在進行鏡像備份時,是否進行壓縮。
●dbfilename
鏡像備份文件的文件名。
●dir
數據庫鏡像備份的文件放置的路徑。這裏的路徑跟文件名要分開配置是由於Redis在進行備份時,先會將當前數據庫的狀態寫入到一個臨時文件中,等備份完成時,再把該該臨時文件替換爲上面所指定的文件,而這裏的臨時文件和上面所配置的備份文件都會放在這個指定的路徑當中。
●slaveof
設置該數據庫爲其餘數據庫的從數據庫。
●masterauth
當主數據庫鏈接須要密碼驗證時,在這裏指定。
●requirepass
設置客戶端鏈接後進行任何其餘指定前須要使用的密碼。警告:由於redis速度至關快,因此在一臺比較好的服務器下,一個外部的用戶能夠在一秒鐘進行150K次的密碼嘗試,這意味着你須要指定很是很是強大的密碼來防止暴力破解。
●maxclients
限制同時鏈接的客戶數量。當鏈接數超過這個值時,redis將再也不接收其餘鏈接請求,客戶端嘗試鏈接時將收到error信息。
●maxmemory
設置redis可以使用的最大內存。當內存滿了的時候,若是還接收到set命令,redis將先嚐試剔除設置過expire信息的key,而無論該key的過時時間尚未到達。在刪除時,將按照過時時間進行刪除,最先將要被過時的key將最早被刪除。若是帶有expire信息的key都刪光了,那麼將返回錯誤。這樣,redis將再也不接收寫請求,只接收get請求。maxmemory的設置比較適合於把redis看成於相似memcached的緩存來使用。
●appendonly
默認狀況下,redis會在後臺異步的把數據庫鏡像備份到磁盤,可是該備份是很是耗時的,並且備份也不能很頻繁,若是發生諸如拉閘限電、拔插頭等情況,那麼將形成比較大範圍的數據丟失。因此redis提供了另一種更加高效的數據庫備份及災難恢復方式。開啓append only模式以後,redis會把所接收到的每一次寫操做請求都追加到appendonly.aof文件中,當redis從新啓動時,會從該文件恢復出以前的狀態。可是這樣會形成appendonly.aof文件過大,因此redis還支持了BGREWRITEAOF指令,對appendonly.aof進行從新整理。因此我認爲推薦生產環境下的作法爲關閉鏡像,開啓appendonly.aof,同時能夠選擇在訪問較少的時間天天對appendonly.aof進行重寫一次。
●appendfsync
設置對appendonly.aof文件進行同步的頻率。always表示每次有寫操做都進行同步,everysec表示對寫操做進行累積,每秒同步一次。這個須要根據實際業務場景進行配置。
●vm-enabled
是否開啓虛擬內存支持。由於redis是一個內存數據庫,並且當內存滿的時候,沒法接收新的寫請求,因此在redis 2.0中,提供了虛擬內存的支持。可是須要注意的是,redis中,全部的key都會放在內存中,在內存不夠時,只會把value值放入交換區。這樣保證了雖然使用虛擬內存,但性能基本不受影響,同時,你須要注意的是你要把vm-max-memory設置到足夠來放下你的全部的key。
●vm-swap-file
設置虛擬內存的交換文件路徑。
●vm-max-memory
這裏設置開啓虛擬內存以後,redis將使用的最大物理內存的大小。默認爲0,redis將把他全部的能放到交換文件的都放到交換文件中,以儘可能少的使用物理內存。在生產環境下,須要根據實際狀況設置該值,最好不要使用默認的0。
●vm-page-size
設置虛擬內存的頁大小,若是你的value值比較大,好比說你要在value中放置博客、新聞之類的全部文章內容,就設大一點,若是要放置的都是很小的內容,那就設小一點。
●vm-pages
設置交換文件的總的page數量,須要注意的是,page table信息會放在物理內存中,每8個page就會佔據RAM中的1個byte。總的虛擬內存大小 = vm-page-size * vm-pages。
●vm-max-threads
設置VM IO同時使用的線程數量。由於在進行內存交換時,對數據有編碼和解碼的過程,因此儘管IO設備在硬件上本上不能支持不少的併發讀寫,可是仍是若是你所保存的vlaue值比較大,將該值設大一些,仍是可以提高性能的。
●glueoutputbuf
把小的輸出緩存放在一塊兒,以便可以在一個TCP packet中爲客戶端發送多個響應,具體原理和真實效果我不是很清楚。因此根據註釋,你不是很肯定的時候就設置成yes。
●hash-max-zipmap-entries
在redis 2.0中引入了hash數據結構。當hash中包含超過指定元素個數而且最大的元素沒有超過臨界時,hash將以一種特殊的編碼方式(大大減小內存使用)來存儲,這裏能夠設置這兩個臨界值。
●activerehashing
開啓以後,redis將在每100毫秒時使用1毫秒的CPU時間來對redis的hash表進行從新hash,能夠下降內存的使用。當你的使用場景中,有很是嚴格的實時性須要,不可以接受Redis時不時的對請求有2毫秒的延遲的話,把這項配置爲no。若是沒有這麼嚴格的實時性要求,能夠設置爲yes,以便可以儘量快的釋放內存。數據結構
4、操做Redis
一、插入數據
redis 127.0.0.1:6379> set name wwl
OK
設置一個key-value對。
二、查詢數據
redis 127.0.0.1:6379> get name
「wwl」
取出key所對應的value。
三、刪除鍵值
redis 127.0.0.1:6379> del name
刪除這個key及對應的value。
四、驗證鍵是否存在
redis 127.0.0.1:6379> exists name
(integer) 0
其中0,表明此key不存在;1表明存在。
5、各種型的基本操做
1)strings類型及操做
string是最簡單的類型,你能夠理解成與Memcached是如出一轍的類型,一個key對應一個value,其上支持的操做與Memcached的操做相似。但它的功能更豐富。
string類型是二進制安全的。意思是redis的string能夠包含任何數據,好比jpg圖片或者序列化的對象。從內部實現來看其實string能夠看做byte數組,最大上限是1G字節,下面是string類型的定義:
struct sdshdr {
long len;
long free;
char buf[];
};
len是buf數組的長度。
free是數組中剩餘可用字節數,由此能夠理解爲何string類型是二進制安全的了,由於它本質上就是個byte數組,固然能夠包含任何數據了
buf是個char數組用於存貯實際的字符串內容,其實char和c#中的byte是等價的,都是一個字節。
另外string類型能夠被部分命令按int處理.好比incr等命令,若是隻用string類型,redis就能夠被看做加上持久化特性的memcached。固然redis對string類型的操做比memcached仍是多不少的,具體操做方法以下:
一、set
設置key對應的值爲string類型的value。
例如咱們添加一個name= HongWan的鍵值對,能夠這樣作:
redis 127.0.0.1:6379> set name HongWan
OK
redis 127.0.0.1:6379>
二、setnx
設置key對應的值爲string類型的value。若是key已經存在,返回0,nx是not exist的意思。
例如咱們添加一個name= HongWan_new的鍵值對,能夠這樣作:
redis 127.0.0.1:6379> get name
「HongWan」
redis 127.0.0.1:6379> setnx name HongWan_new
(integer) 0
redis 127.0.0.1:6379> get name
「HongWan」
redis 127.0.0.1:6379>
因爲原來name有一個對應的值,因此本次的修改不生效,且返回碼是0。
三、setex
設置key對應的值爲string類型的value,並指定此鍵值對應的有效期。
例如咱們添加一個haircolor= red的鍵值對,並指定它的有效期是10秒,能夠這樣作:
redis 127.0.0.1:6379> setex haircolor 10 red
OK
redis 127.0.0.1:6379> get haircolor
「red」
redis 127.0.0.1:6379> get haircolor
(nil)
redis 127.0.0.1:6379>
可見因爲最後一次的調用是10秒之後了,因此取不到haicolor這個鍵對應的值。
四、setrange
設置指定key的value值的子字符串。
例如咱們但願將HongWan的126郵箱替換爲gmail郵箱,那麼咱們能夠這樣作:
redis 127.0.0.1:6379> get name
「HongWan@126.com」
redis 127.0.0.1:6379> setrange name 8 gmail.com
(integer) 17
redis 127.0.0.1:6379> get name
「HongWan@gmail.com」
redis 127.0.0.1:6379>
其中的8是指從下標爲8(包含8)的字符開始替換
五、mset
一次設置多個key的值,成功返回ok表示全部的值都設置了,失敗返回0表示沒有任何值被設置。
redis 127.0.0.1:6379> mset key1 HongWan1 key2 HongWan2
OK
redis 127.0.0.1:6379> get key1
「HongWan1″
redis 127.0.0.1:6379> get key2
「HongWan2″
redis 127.0.0.1:6379>
六、msetnx
一次設置多個key的值,成功返回ok表示全部的值都設置了,失敗返回0表示沒有任何值被設置,可是不會覆蓋已經存在的key。
redis 127.0.0.1:6379> get key1
「HongWan1″
redis 127.0.0.1:6379> get key2
「HongWan2″
redis 127.0.0.1:6379> msetnx key2 HongWan2_new key3 HongWan3
(integer) 0
redis 127.0.0.1:6379> get key2
「HongWan2″
redis 127.0.0.1:6379> get key3
(nil)
能夠看出若是這條命令返回0,那麼裏面操做都會回滾,都不會被執行。
七、get
獲取key對應的string值,若是key不存在返回nil。
例如咱們獲取一個庫中存在的鍵name,能夠很快獲得它對應的value
redis 127.0.0.1:6379> get name
「HongWan」
redis 127.0.0.1:6379>
咱們獲取一個庫中不存在的鍵name1,那麼它會返回一個nil以表時無此鍵值對
redis 127.0.0.1:6379> get name1
(nil)
redis 127.0.0.1:6379>
八、getset
設置key的值,並返回key的舊值。
redis 127.0.0.1:6379> get name
「HongWan」
redis 127.0.0.1:6379> getset name HongWan_new
「HongWan」
redis 127.0.0.1:6379> get name
「HongWan_new」
redis 127.0.0.1:6379>
接下來咱們看一下若是key不存的時候會什麼樣兒?
redis 127.0.0.1:6379> getset name1 aaa
(nil)
redis 127.0.0.1:6379>
可見,若是key不存在,那麼將返回nil
九、getrange
獲取指定key的value值的子字符串。
具體樣例以下:
redis 127.0.0.1:6379> get name
「HongWan@126.com」
redis 127.0.0.1:6379> getrange name 0 6
「HongWan」
redis 127.0.0.1:6379>
字符串左面下標是從0開始的
redis 127.0.0.1:6379> getrange name -7 -1
「126.com」
redis 127.0.0.1:6379>
字符串右面下標是從-1開始的
redis 127.0.0.1:6379> getrange name 7 100
「@126.com」
redis 127.0.0.1:6379>
當下標超出字符串長度時,將默認爲是同方向的最大下標
十、mget
一次獲取多個key的值,若是對應key不存在,則對應返回nil。
具體樣例以下:
redis 127.0.0.1:6379> mget key1 key2 key3
1) 「HongWan1″
2) 「HongWan2″
3) (nil)
redis 127.0.0.1:6379>
key3因爲沒有這個鍵定義,因此返回nil。
十一、incr
對key的值作加加操做,並返回新的值。注意incr一個不是int的value會返回錯誤,incr一個不存在的key,則設置key爲1
redis 127.0.0.1:6379> set age 20
OK
redis 127.0.0.1:6379> incr age
(integer) 21
redis 127.0.0.1:6379> get age
「21」
redis 127.0.0.1:6379>
十二、incrby
同incr相似,加指定值 ,key不存在時候會設置key,並認爲原來的value是 0
redis 127.0.0.1:6379> get age
「21」
redis 127.0.0.1:6379> incrby age 5
(integer) 26
redis 127.0.0.1:6379> get name
「HongWan@gmail.com」
redis 127.0.0.1:6379> get age
「26」
redis 127.0.0.1:6379>
1三、decr
對key的值作的是減減操做,decr一個不存在key,則設置key爲-1
redis 127.0.0.1:6379> get age
「26」
redis 127.0.0.1:6379> decr age
(integer) 25
redis 127.0.0.1:6379> get age
「25」
redis 127.0.0.1:6379>
1四、decrby
同decr,減指定值。
redis 127.0.0.1:6379> get age
「25」
redis 127.0.0.1:6379> decrby age 5
(integer) 20
redis 127.0.0.1:6379> get age
「20」
redis 127.0.0.1:6379>
decrby徹底是爲了可讀性,咱們徹底能夠經過incrby一個負值來實現一樣效果,反之同樣。
redis 127.0.0.1:6379> get age
「20」
redis 127.0.0.1:6379> incrby age -5
(integer) 15
redis 127.0.0.1:6379> get age
「15」
redis 127.0.0.1:6379>
1五、append
給指定key的字符串值追加value,返回新字符串值的長度。例如咱們向name的值追加一個@126.com字符串,那麼能夠這樣作:
redis 127.0.0.1:6379> append name @126.com
(integer) 15
redis 127.0.0.1:6379> get name
「HongWan@126.com」
redis 127.0.0.1:6379>
1六、strlen
取指定key的value值的長度。
redis 127.0.0.1:6379> get name
「HongWan_new」
redis 127.0.0.1:6379> strlen name
(integer) 11
redis 127.0.0.1:6379> get age
「15」
redis 127.0.0.1:6379> strlen age
(integer) 2
redis 127.0.0.1:6379>
2)hash
Redis hash是一個string類型的field和value的映射表.它的添加、刪除操做都是O(1)(平均)。hash特別適合用於存儲對象。相較於將對象的每一個字段存成單個string類型。將一個對象存儲在hash類型中會佔用更少的內存,而且能夠更方便的存取整個對象。省內存的緣由是新建一個hash對象時開始是用zipmap(又稱爲small hash)來存儲的。這個zipmap其實並非hash table,可是zipmap相比正常的hash實現能夠節省很多hash自己須要的一些元數據存儲開銷。儘管zipmap的添加,刪除,查找都是O(n),可是因爲通常對象的field數量都不太多。因此使用zipmap也是很快的,也就是說添加刪除平均仍是O(1)。若是field或者value的大小超出必定限制後,Redis會在內部自動將zipmap替換成正常的hash實現. 這個限制能夠在配置文件中指定
hash-max-zipmap-entries 64 #配置字段最多64個。
hash-max-zipmap-value 512 #配置value最大爲512字節。
一、hset
設置hash field爲指定值,若是key不存在,則先建立。
redis 127.0.0.1:6379> hset myhash field1 Hello
(integer) 1
redis 127.0.0.1:6379>
二、hsetnx
設置hash field爲指定值,若是key不存在,則先建立。若是field已經存在,返回0,nx是not exist的意思。
redis 127.0.0.1:6379> hsetnx myhash field 「Hello」
(integer) 1
redis 127.0.0.1:6379> hsetnx myhash field 「Hello」
(integer) 0
redis 127.0.0.1:6379>
第一次執行是成功的,但第二次執行相同的命令失敗,緣由是field已經存在了。
三、hmset
同時設置hash的多個field。
redis 127.0.0.1:6379> hmset myhash field1 Hello field2 World
OK
redis 127.0.0.1:6379>
四、hget
獲取指定的hash field。
redis 127.0.0.1:6379> hget myhash field1
「Hello」
redis 127.0.0.1:6379> hget myhash field2
「World」
redis 127.0.0.1:6379> hget myhash field3
(nil)
redis 127.0.0.1:6379>
因爲數據庫沒有field3,因此取到的是一個空值nil。
五、hmget
獲取所有指定的hash filed。
redis 127.0.0.1:6379> hmget myhash field1 field2 field3
1) 「Hello」
2) 「World」
3) (nil)
redis 127.0.0.1:6379>
因爲數據庫沒有field3,因此取到的是一個空值nil。
六、hincrby
指定的hash filed 加上給定值。
redis 127.0.0.1:6379> hset myhash field3 20
(integer) 1
redis 127.0.0.1:6379> hget myhash field3
「20」
redis 127.0.0.1:6379> hincrby myhash field3 -8
(integer) 12
redis 127.0.0.1:6379> hget myhash field3
「12」
redis 127.0.0.1:6379>
在本例中咱們將field3的值從20降到了12,即作了一個減8的操做。
七、hexists
測試指定field是否存在。
redis 127.0.0.1:6379> hexists myhash field1
(integer) 1
redis 127.0.0.1:6379> hexists myhash field9
(integer) 0
redis 127.0.0.1:6379>
經過上例能夠說明field1存在,但field9是不存在的。
八、hlen
返回指定hash的field數量。
redis 127.0.0.1:6379> hlen myhash
(integer) 4
redis 127.0.0.1:6379>
經過上例能夠看到myhash中有4個field。
九、hdel
返回指定hash的field數量。
redis 127.0.0.1:6379> hlen myhash
(integer) 4
redis 127.0.0.1:6379> hdel myhash field1
(integer) 1
redis 127.0.0.1:6379> hlen myhash
(integer) 3
redis 127.0.0.1:6379>
十、hkeys
返回hash的全部field。
redis 127.0.0.1:6379> hkeys myhash
1) 「field2″
2) 「field」
3) 「field3″
redis 127.0.0.1:6379>
說明這個hash中有3個field。
十一、hvals
返回hash的全部value。
redis 127.0.0.1:6379> hvals myhash
1) 「World」
2) 「Hello」
3) 「12」
redis 127.0.0.1:6379>
說明這個hash中有3個field。
十二、hgetall
獲取某個hash中所有的filed及value。
redis 127.0.0.1:6379> hgetall myhash
1) 「field2″
2) 「World」
3) 「field」
4) 「Hello」
5) 「field3″
6) 「12」
redis 127.0.0.1:6379>
可見,一會兒將myhash中全部的field及對應的value都取出來了。
3)list
Redis的list類型其實就是一個每一個子元素都是string類型的雙向鏈表。鏈表的最大長度是(2的32次方)。咱們能夠經過push,pop操做從鏈表的頭部或者尾部添加刪除元素。這使得list既能夠用做棧,也能夠用做隊列。
有意思的是list的pop操做還有阻塞版本的,當咱們[lr]pop一個list對象時,若是list是空,或者不存在,會當即返回nil。可是阻塞版本的b[lr]pop能夠則能夠阻塞,固然能夠加超時時間,超時後也會返回nil。爲何要阻塞版本的pop呢,主要是爲了不輪詢。舉個簡單的例子若是咱們用list來實現一個工做隊列。執行任務的thread能夠調用阻塞版本的pop去獲取任務這樣就能夠避免輪詢去檢查是否有任務存在。當任務來時候工做線程能夠當即返回,也能夠避免輪詢帶來的延遲。說了這麼多,接下來看一下實際操做的方法吧:
一、lpush
在key對應list的頭部添加字符串元素:
redis 127.0.0.1:6379> lpush mylist 「world」
(integer) 1
redis 127.0.0.1:6379> lpush mylist 「hello」
(integer) 2
redis 127.0.0.1:6379> lrange mylist 0 -1
1) 「hello」
2) 「world」
redis 127.0.0.1:6379>
在此處咱們先插入了一個world,而後在world的頭部插入了一個hello。其中lrange是用於取mylist的內容。
二、rpush
在key對應list的尾部添加字符串元素:
redis 127.0.0.1:6379> rpush mylist2 「hello」
(integer) 1
redis 127.0.0.1:6379> rpush mylist2 「world」
(integer) 2
redis 127.0.0.1:6379> lrange mylist2 0 -1
1) 「hello」
2) 「world」
redis 127.0.0.1:6379>
在此處咱們先插入了一個hello,而後在hello的尾部插入了一個world。
三、linsert
在key對應list的特定位置以前或以後添加字符串元素:
redis 127.0.0.1:6379> rpush mylist3 「hello」
(integer) 1
redis 127.0.0.1:6379> rpush mylist3 「world」
(integer) 2
redis 127.0.0.1:6379> linsert mylist3 before 「world」 「there」
(integer) 3
redis 127.0.0.1:6379> lrange mylist3 0 -1
1) 「hello」
2) 「there」
3) 「world」
redis 127.0.0.1:6379>
在此處咱們先插入了一個hello,而後在hello的尾部插入了一個world,而後又在world的前面插入了there。
四、lset
設置list中指定下標的元素值(下標從0開始):
redis 127.0.0.1:6379> rpush mylist4 「one」
(integer) 1
redis 127.0.0.1:6379> rpush mylist4 「two」
(integer) 2
redis 127.0.0.1:6379> rpush mylist4 「three」
(integer) 3
redis 127.0.0.1:6379> lset mylist4 0 「four」
OK
redis 127.0.0.1:6379> lset mylist4 -2 「five」
OK
redis 127.0.0.1:6379> lrange mylist4 0 -1
1) 「four」
2) 「five」
3) 「three」
redis 127.0.0.1:6379>
在此處咱們依次插入了one,two,three,而後將標是0的值設置爲four,再將下標是-2的值設置爲five。
五、lrem
從key對應list中刪除count個和value相同的元素。
count>0時,按從頭至尾的順序刪除,具體以下:
redis 127.0.0.1:6379> rpush mylist5 「hello」
(integer) 1
redis 127.0.0.1:6379> rpush mylist5 「hello」
(integer) 2
redis 127.0.0.1:6379> rpush mylist5 「foo」
(integer) 3
redis 127.0.0.1:6379> rpush mylist5 「hello」
(integer) 4
redis 127.0.0.1:6379> lrem mylist5 2 「hello」
(integer) 2
redis 127.0.0.1:6379> lrange mylist5 0 -1
1) 「foo」
2) 「hello」
redis 127.0.0.1:6379>
count<0時,按從尾到頭的順序刪除,具體以下:
redis 127.0.0.1:6379> rpush mylist6 「hello」
(integer) 1
redis 127.0.0.1:6379> rpush mylist6 「hello」
(integer) 2
redis 127.0.0.1:6379> rpush mylist6 「foo」
(integer) 3
redis 127.0.0.1:6379> rpush mylist6 「hello」
(integer) 4
redis 127.0.0.1:6379> lrem mylist6 -2 「hello」
(integer) 2
redis 127.0.0.1:6379> lrange mylist6 0 -1
1) 「hello」
2) 「foo」
redis 127.0.0.1:6379>
count=0時,刪除所有,具體以下:
redis 127.0.0.1:6379> rpush mylist7 「hello」
(integer) 1
redis 127.0.0.1:6379> rpush mylist7 「hello」
(integer) 2
redis 127.0.0.1:6379> rpush mylist7 「foo」
(integer) 3
redis 127.0.0.1:6379> rpush mylist7 「hello」
(integer) 4
redis 127.0.0.1:6379> lrem mylist7 0 「hello」
(integer) 3
redis 127.0.0.1:6379> lrange mylist7 0 -1
1) 「foo」
redis 127.0.0.1:6379>
六、ltrim
保留指定key 的值範圍內的數據:
redis 127.0.0.1:6379> rpush mylist8 「one」
(integer) 1
redis 127.0.0.1:6379> rpush mylist8 「two」
(integer) 2
redis 127.0.0.1:6379> rpush mylist8 「three」
(integer) 3
redis 127.0.0.1:6379> rpush mylist8 「four」
(integer) 4
redis 127.0.0.1:6379> ltrim mylist8 1 -1
OK
redis 127.0.0.1:6379> lrange mylist8 0 -1
1) 「two」
2) 「three」
3) 「four」
redis 127.0.0.1:6379>
七、lpop
從list的頭部刪除元素,並返回刪除元素:
redis 127.0.0.1:6379> lrange mylist 0 -1
1) 「hello」
2) 「world」
redis 127.0.0.1:6379> lpop mylist
「hello」
redis 127.0.0.1:6379> lrange mylist 0 -1
1) 「world」
redis 127.0.0.1:6379>
八、rpop
從list的尾部刪除元素,並返回刪除元素:
redis 127.0.0.1:6379> lrange mylist2 0 -1
1) 「hello」
2) 「world」
redis 127.0.0.1:6379> rpop mylist2
「world」
redis 127.0.0.1:6379> lrange mylist2 0 -1
1) 「hello」
redis 127.0.0.1:6379>
九、rpoplpush
從第一個list的尾部移除元素並添加到第二個list的頭部,最後返回被移除的元素值,整個操做是原子的.若是第一個list是空或者不存在返回nil:
redis 127.0.0.1:6379> lrange mylist5 0 -1
1) 「three」
2) 「foo」
3) 「hello」
redis 127.0.0.1:6379> lrange mylist6 0 -1
1) 「hello」
2) 「foo」
redis 127.0.0.1:6379> rpoplpush mylist5 mylist6
「hello」
redis 127.0.0.1:6379> lrange mylist5 0 -1
1) 「three」
2) 「foo」
redis 127.0.0.1:6379> lrange mylist6 0 -1
1) 「hello」
2) 「hello」
3) 「foo」
redis 127.0.0.1:6379>
十、lindex
返回名稱爲key的list中index位置的元素:
redis 127.0.0.1:6379> lrange mylist5 0 -1
1) 「three」
2) 「foo」
redis 127.0.0.1:6379> lindex mylist5 0
「three」
redis 127.0.0.1:6379> lindex mylist5 1
「foo」
redis 127.0.0.1:6379>
十一、llen
返回key對應list的長度:
redis 127.0.0.1:6379> llen mylist5
(integer) 2
redis 127.0.0.1:6379>
4)sets
Redis的set是string類型的無序集合。set元素最大能夠包含(2的32次方)個元素。
set的是經過hash table實現的,因此添加、刪除和查找的複雜度都是O(1)。hash table會隨着添加或者刪除自動的調整大小。須要注意的是調整hash table大小時候須要同步(獲取寫鎖)會阻塞其餘讀寫操做,可能不久後就會改用跳錶(skip list)來實現,跳錶已經在sorted set中使用了。關於set集合類型除了基本的添加刪除操做,其餘有用的操做還包含集合的取並集(union),交集(intersection),差集(difference)。經過這些操做能夠很容易的實現sns中的好友推薦和blog的tag功能。下面詳細介紹set相關命令:
一、sadd
向名稱爲key的set中添加元素:
redis 127.0.0.1:6379> sadd myset 「hello」
(integer) 1
redis 127.0.0.1:6379> sadd myset 「world」
(integer) 1
redis 127.0.0.1:6379> sadd myset 「world」
(integer) 0
redis 127.0.0.1:6379> smembers myset
1) 「world」
2) 「hello」
redis 127.0.0.1:6379>
本例中,咱們向myset中添加了三個元素,但因爲第三個元素跟第二個元素是相同的,因此第三個元素沒有添加成功,最後咱們用smembers來查看myset中的全部元素。
二、srem
刪除名稱爲key的set中的元素member:
redis 127.0.0.1:6379> sadd myset2 「one」
(integer) 1
redis 127.0.0.1:6379> sadd myset2 「two」
(integer) 1
redis 127.0.0.1:6379> sadd myset2 「three」
(integer) 1
redis 127.0.0.1:6379> srem myset2 「one」
(integer) 1
redis 127.0.0.1:6379> srem myset2 「four」
(integer) 0
redis 127.0.0.1:6379> smembers myset2
1) 「three」
2) 「two」
redis 127.0.0.1:6379>
本例中,咱們向myset2中添加了三個元素後,再調用srem來刪除one和four,但因爲元素中沒有four因此,此條srem命令執行失敗。
三、spop
隨機返回並刪除名稱爲key的set中一個元素:
redis 127.0.0.1:6379> sadd myset2 「one」
(integer) 1
redis 127.0.0.1:6379> sadd myset2 「two」
(integer) 1
redis 127.0.0.1:6379> sadd myset2 「three」
(integer) 1
redis 127.0.0.1:6379> srem myset2 「one」
(integer) 1
redis 127.0.0.1:6379> srem myset2 「four」
(integer) 0
redis 127.0.0.1:6379> smembers myset2
1) 「three」
2) 「two」
redis 127.0.0.1:6379>
本例中,咱們向myset3中添加了三個元素後,再調用spop來隨機刪除一個元素,能夠看到three元素被刪除了。
四、sdiff
返回全部給定key與第一個key的差集:
redis 127.0.0.1:6379> sadd myset2 「one」
(integer) 1
redis 127.0.0.1:6379> sadd myset2 「two」
(integer) 1
redis 127.0.0.1:6379> sadd myset2 「three」
(integer) 1
redis 127.0.0.1:6379> srem myset2 「one」
(integer) 1
redis 127.0.0.1:6379> srem myset2 「four」
(integer) 0
redis 127.0.0.1:6379> smembers myset2
1) 「three」
2) 「two」
redis 127.0.0.1:6379>
本例中,咱們能夠看到myset2中的元素與myset3中不一樣的只是three,因此只有three被查出來了,而不是three和one,由於one是myset3的元素。
咱們也能夠將myset2和myset3換個順序來看一下結果:
redis 127.0.0.1:6379> sdiff myset3 myset2
1) 「one」
redis 127.0.0.1:6379>
這個結果中只顯示了,myset3中的元素與myset2中不一樣的元素。
五、sdiffstore
返回全部給定key與第一個key的差集,並將結果存爲另外一個key:
redis 127.0.0.1:6379> smembers myset2
1) 「three」
2) 「two」
redis 127.0.0.1:6379> smembers myset3
1) 「two」
2) 「one」
redis 127.0.0.1:6379> sdiffstore myset4 myset2 myset3
(integer) 1
redis 127.0.0.1:6379> smembers myset4
1) 「three」
redis 127.0.0.1:6379>
六、sinter
返回全部給定key的交集:
redis 127.0.0.1:6379> smembers myset2
1) 「three」
2) 「two」
redis 127.0.0.1:6379> smembers myset3
1) 「two」
2) 「one」
redis 127.0.0.1:6379> sinter myset2 myset3
1) 「two」
redis 127.0.0.1:6379>
經過本例的結果能夠看出, myset2和myset3的交集two被查出來了。
七、sinterstore
返回全部給定key的交集,並將結果存爲另外一個key
redis 127.0.0.1:6379> smembers myset2
1) 「three」
2) 「two」
redis 127.0.0.1:6379> smembers myset3
1) 「two」
2) 「one」
redis 127.0.0.1:6379> sinterstore myset5 myset2 myset3
(integer) 1
redis 127.0.0.1:6379> smembers myset5
1) 「two」
redis 127.0.0.1:6379>
經過本例的結果能夠看出, myset2和myset3的交集被保存到myset5中了
八、sunion
返回全部給定key的並集
redis 127.0.0.1:6379> smembers myset2
1) 「three」
2) 「two」
redis 127.0.0.1:6379> smembers myset3
1) 「two」
2) 「one」
redis 127.0.0.1:6379> sunion myset2 myset3
1) 「three」
2) 「one」
3) 「two」
redis 127.0.0.1:6379>
經過本例的結果能夠看出, myset2和myset3的並集被查出來了
九、sunionstore
返回全部給定key的並集,並將結果存爲另外一個key
redis 127.0.0.1:6379> smembers myset2
1) 「three」
2) 「two」
redis 127.0.0.1:6379> smembers myset3
1) 「two」
2) 「one」
redis 127.0.0.1:6379> sunionstore myset6 myset2 myset3
(integer) 3
redis 127.0.0.1:6379> smembers myset6
1) 「three」
2) 「one」
3) 「two」
redis 127.0.0.1:6379>
經過本例的結果能夠看出, myset2和myset3的並集被保存到myset6中了
十、smove
從第一個key對應的set中移除member並添加到第二個對應set中
redis 127.0.0.1:6379> smembers myset2
1) 「three」
2) 「two」
redis 127.0.0.1:6379> smembers myset3
1) 「two」
2) 「one」
redis 127.0.0.1:6379> smove myset2 myset7 three
(integer) 1
redis 127.0.0.1:6379> smembers myset7
1) 「three」
redis 127.0.0.1:6379>
經過本例能夠看到,myset2的three被移到myset7中了
十一、scard
返回名稱爲key的set的元素個數
redis 127.0.0.1:6379> scard myset2
(integer) 1
redis 127.0.0.1:6379>
經過本例能夠看到,myset2的成員數量爲1
十二、sismember
測試member是不是名稱爲key的set的元素
redis 127.0.0.1:6379> smembers myset2
1) 「two」
redis 127.0.0.1:6379> sismember myset2 two
(integer) 1
redis 127.0.0.1:6379> sismember myset2 one
(integer) 0
redis 127.0.0.1:6379>
經過本例能夠看到,two是myset2的成員,而one不是。
1三、srandmember
隨機返回名稱爲key的set的一個元素,可是不刪除元素
redis 127.0.0.1:6379> smembers myset3
1) 「two」
2) 「one」
redis 127.0.0.1:6379> srandmember myset3
「two」
redis 127.0.0.1:6379> srandmember myset3
「one」
redis 127.0.0.1:6379>
5)sorted sets
和set同樣sorted set也是string類型元素的集合,不一樣的是每一個元素都會關聯一個double類型的score。sorted set的實現是skip list和hash table的混合體。
當元素被添加到集合中時,一個元素到score的映射被添加到hash table中,因此給定一個元素獲取score的開銷是O(1),另外一個score到元素的映射被添加到skip list,並按照score排序,因此就能夠有序的獲取集合中的元素。添加,刪除操做開銷都是O(log(N))和skip list的開銷一致,redis的skip list實現用的是雙向鏈表,這樣就能夠逆序從尾部取元素。sorted set最常常的使用方式應該是做爲索引來使用.咱們能夠把要排序的字段做爲score存儲,對象的id當元素存儲。下面是sorted set相關命令
一、zadd
向名稱爲key的zset中添加元素member,score用於排序。若是該元素已經存在,則根據score更新該元素的順序
redis 127.0.0.1:6379> zadd myzset 1 「one」
(integer) 1
redis 127.0.0.1:6379> zadd myzset 2 「two」
(integer) 1
redis 127.0.0.1:6379> zadd myzset 3 「two」
(integer) 0
redis 127.0.0.1:6379> zrange myzset 0 -1 withscores
1) 「one」
2) 「1」
3) 「two」
4) 「3」
redis 127.0.0.1:6379>
本例中咱們向myzset中添加了one和two,而且two被設置了2次,那麼將以最後一次的設置爲準,最後咱們將全部元素都顯示出來並顯示出了元素的score。
二、zrem
刪除名稱爲key的zset中的元素member
redis 127.0.0.1:6379> zrange myzset 0 -1 withscores
1) 「one」
2) 「1」
3) 「two」
4) 「3」
redis 127.0.0.1:6379> zrem myzset two
(integer) 1
redis 127.0.0.1:6379> zrange myzset 0 -1 withscores
1) 「one」
2) 「1」
redis 127.0.0.1:6379>
能夠看到two被刪除了
三、zincrby
若是在名稱爲key的zset中已經存在元素member,則該元素的score增長increment;不然向集合中添加該元素,其score的值爲increment
redis 127.0.0.1:6379> zadd myzset2 1 「one」
(integer) 1
redis 127.0.0.1:6379> zadd myzset2 2 「two」
(integer) 1
redis 127.0.0.1:6379> zincrby myzset2 2 「one」
「3」
redis 127.0.0.1:6379> zrange myzset2 0 -1 withscores
1) 「two」
2) 「2」
3) 「one」
4) 「3」
redis 127.0.0.1:6379>
本例中將one的score從1增長了2,增長到了3
四、zrank
返回名稱爲key的zset中member元素的排名(按score從小到大排序)即下標
redis 127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) 「one」
2) 「1」
3) 「two」
4) 「2」
5) 「three」
6) 「3」
7) 「five」
8) 「5」
redis 127.0.0.1:6379> zrank myzset3 two
(integer) 1
redis 127.0.0.1:6379>
本例中將two的下標是1,我這裏取的是下標,而不是score
五、zrevrank
返回名稱爲key的zset中member元素的排名(按score從大到小排序)即下標
redis 127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) 「one」
2) 「1」
3) 「two」
4) 「2」
5) 「three」
6) 「3」
7) 「five」
8) 「5」
redis 127.0.0.1:6379> zrank myzset3 two
(integer) 1
redis 127.0.0.1:6379>
按從大到小排序的話two是第三個元素,下標是2
六、zrevrange
返回名稱爲key的zset(按score從大到小排序)中的index從start到end的全部元素
redis 127.0.0.1:6379> zrevrange myzset3 0 -1 withscores
1) 「five」
2) 「5」
3) 「three」
4) 「3」
5) 「two」
6) 「2」
7) 「one」
8) 「1」
redis 127.0.0.1:6379>
首先按score從大到小排序,再取出所有元素
七、zrangebyscore
返回集合中score在給定區間的元素
redis 127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) 「one」
2) 「1」
3) 「two」
4) 「2」
5) 「three」
6) 「3」
7) 「five」
8) 「5」
redis 127.0.0.1:6379> zrangebyscore myzset3 2 3 withscores
1) 「two」
2) 「2」
3) 「three」
4) 「3」
redis 127.0.0.1:6379>
本例中,返回了score在2~3區間的元素
八、zcount
返回集合中score在給定區間的數量
redis 127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) 「one」
2) 「1」
3) 「two」
4) 「2」
5) 「three」
6) 「3」
7) 「five」
8) 「5」
redis 127.0.0.1:6379> zcount myzset3 2 3
(integer) 2
redis 127.0.0.1:6379>
本例中,計算了score在2~3之間的元素數目
九、zcard
返回集合中元素個數
redis 127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) 「one」
2) 「1」
3) 「two」
4) 「2」
5) 「three」
6) 「3」
7) 「five」
8) 「5」
redis 127.0.0.1:6379> zcard myzset3
(integer) 4
redis 127.0.0.1:6379>
從本例看出myzset3這個集全的元素數量是4
十、zscore
返回給定元素對應的score
redis 127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) 「one」
2) 「1」
3) 「two」
4) 「2」
5) 「three」
6) 「3」
7) 「five」
8) 「5」
redis 127.0.0.1:6379> zscore myzset3 two
「2」
redis 127.0.0.1:6379>
此例中咱們成功的將two的score取出來了。
十一、zremrangebyrank
刪除集合中排名在給定區間的元素
redis 127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) 「one」
2) 「1」
3) 「two」
4) 「2」
5) 「three」
6) 「3」
7) 「five」
8) 「5」
redis 127.0.0.1:6379> zremrangebyrank myzset3 3 3
(integer) 1
redis 127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) 「one」
2) 「1」
3) 「two」
4) 「2」
5) 「three」
6) 「3」
redis 127.0.0.1:6379>
在本例中咱們將myzset3中按從小到大排序結果的下標爲3的元素刪除了。
十二、zremrangebyscore刪除集合中score在給定區間的元素redis 127.0.0.1:6379> zrange myzset3 0 -1 withscores1) 「one」2) 「1」3) 「two」4) 「2」5) 「three」6) 「3」redis 127.0.0.1:6379> zremrangebyscore myzset3 1 2(integer) 2redis 127.0.0.1:6379> zrange myzset3 0 -1 withscores1) 「three」2) 「3」redis 127.0.0.1:6379>在本例中咱們將myzset3中按從小到大排序結果的score在1~2之間的元素刪除了。