一、簡介: 在過去的幾年中,NoSQL資料庫一度成為高併發、海量數據存儲解決方案的代名詞,與之相應的產品也呈現出雨後春筍般的生機。然而在眾多產品中能夠脫穎而出的卻屈指可數,如Redis、MongoDB、BerkeleyDB和CouchDB等。由於每種產品所擁有的特征不同,因此它們的應用場景也存在著一 ...
一、簡介:
在過去的幾年中,NoSQL資料庫一度成為高併發、海量數據存儲解決方案的代名詞,與之相應的產品也呈現出雨後春筍般的生機。然而在眾多產品中能夠脫穎而出的卻屈指可數,如Redis、MongoDB、BerkeleyDB和CouchDB等。由於每種產品所擁有的特征不同,因此它們的應用場景也存在著一定的差異,下麵僅給出簡單的說明:
1). BerkeleyDB是一種極為流行的開源嵌入式資料庫,在更多情況下可用於存儲引擎,比如BerkeleyDB在被Oracle收購之前曾作為MySQL的存儲引擎,由此可以預見,該產品擁有極好的併發伸縮性,支持事務及嵌套事務,海量數據存儲等重要特征,在用於存儲實時數據方面具有極高的可用價值。然而需要指出的是,該產品的Licence為GPL,這就意味著它並不是在所有情況下都是免費使用的。
2). 對MongoDB的定義為Oriented-Document資料庫伺服器,和BerkeleyDB不同的是該資料庫可以像其他關係型資料庫伺服器那樣獨立的運行並提供相關的數據服務。從該產品的官方文檔中我們可以獲悉,MongoDB主要適用於高併發的論壇或博客網站,這些網站具有的主要特征是併發訪問量高、多讀少寫、數據量大、邏輯關係簡單,以及文檔數據作為主要數據源等。和BerkeleyDB一樣,該產品的License同為GPL。
3). Redis,典型的NoSQL資料庫伺服器,和BerkeleyDB相比,它可以作為服務程式獨立運行於自己的伺服器主機。在很多時候,人們只是將Redis視為Key/Value資料庫伺服器,然而事實並非如此,在目前的版本中,Redis除了Key/Value之外還支持List、Hash、Set和Ordered Set等數據結構,因此它的用途也更為寬泛。對於此種誤解,Redis官網也進行了相應的澄清。和以上兩種產品不同的是,Redis的License是Apache License,就目前而言,它是完全免費。
4). memcached,數據緩存伺服器。它們之間的最大區別,memcached只是提供了數據緩存服務,一旦伺服器宕機,之前在記憶體中緩存的數據也將全部消失,因此可以看出memcached沒有提供任何形式的數據持久化功能,而Redis則提供了這樣的功能。再有就是Redis提供了更為豐富的數據存儲結構,如Hash和Set。至於它們的相同點,主要有兩個,一是完全免費,再有就是它們的提供的命令形式極為接近。
二、redis的優勢:
1). 和其他NoSQL產品相比,Redis的易用性極高,因此對於那些有類似產品使用經驗的開發者來說,一兩天,甚至是幾個小時之後就可以利用Redis來搭建自己的平臺了。
2). 在解決了很多通用性問題的同時,也為一些個性化問題提供了相關的解決方案,如索引引擎、統計排名、消息隊列服務等。
三、安裝以及使用(在linux環境下,至於安裝包去官網下載就可以):
1. 安裝:
1.解壓redis-3.2.8.tar.gz
tar -zxvf redis-3.2.8.tar.gz
2.編譯
cd redis-3.2.8
make
3.安裝命令
cd redis-3.2.8
make PREFIX=/home/soft01/software/redis-bin install
2. 啟動( cd到redis-bin目錄下):
使用預設配置
./redis-server
使用自定義配置文件啟動
./redis-server redis.conf
3.連接redis( cd到redis-bin目錄下):
./redis-cli
4.關閉:
方案一:伺服器視窗中Ctrl+C
方案二:客戶端連接之後 輸入shutdown
5.解決埠占用:
lsof -i:埠
得到PID
kill PID (平滑kill)
kill -9 PID (強制kill)
查看軟體啟動狀態
ps -aux | grep redis
下麵是代碼操作:
1 #### 3.String類型
2
3 ##### 概述
4
5 字元串類型是Redis中最為基礎的數據存儲類型,它在Redis中是二進位安全的,這便意味著該類型可以接受任何格式的數據,如JPEG圖像數據或Json對象描述信息等。在Redis中字元串類型的Value最多可以容納的數據長度是512M。
6
7 ```shell
8 # set/get/append/strlen
9 $ redis-cli
10 127.0.0.1:6379> select 0
11 OK
12 127.0.0.1:6379> exists mykey #判斷該鍵是否存在,存在返回1,不存在返回0
13 (integer) 0
14 127.0.0.1:6379> append mykey "hello" #該鍵不存在,因此append命令返回當前Value的長度。
15 (integer) 5
16 127.0.0.1:6379> append mykey " world" #該鍵已經存在,因此返回追加後Value的長度。
17 (integer) 11
18 127.0.0.1:6379> get mykey #獲取mykey的值
19 "hello world"
20 #設置mykey,存在覆蓋 set mykey "hello" (EX 5 PX s5000 NX/XX) EX和PX表示失效時間,單位為秒和毫秒
21 #NX不存在的時候才會保存,XX存在的時候才會保存
22 127.0.0.1:6379> set mykey "this is test"
23 OK
24 127.0.0.1:6379> get mykey
25 "this is test"
26 127.0.0.1:6379> strlen mykey #獲取mykey的長度
27 (integer) 12
28
29
30 # incr/decr/incrby/decrby
31 127.0.0.1:6379> set mykey 20 XX #設置mykey為20
32 OK
33 127.0.0.1:6379> incr mykey #遞增1
34 (integer) 21
35 127.0.0.1:6379> decr mykey #遞減1
36 (integer) 20
37 127.0.0.1:6379> del mykey #刪除該鍵
38 (integer) 1
39 127.0.0.1:6379> decr mykey
40 (integer) -1
41 127.0.0.1:6379> del mykey
42 (integer) 1
43 127.0.0.1:6379> INCR mykey
44 (integer) 1
45 127.0.0.1:6379> set mykey 'hello' #將該鍵的Value設置為不能轉換為整型的普通字元串。
46 OK
47 127.0.0.1:6379> incr mykey #在該鍵上再次執行遞增操作時,Redis將報告錯誤信息。
48 (error) ERR value is not an integer or out of range
49 127.0.0.1:6379> set mykey 10
50 OK
51 127.0.0.1:6379> decrby mykey 5 #遞減5
52 (integer) 5
53 127.0.0.1:6379> incrby mykey 10 #遞增10
54 (integer) 15
55
56
57 # getset 獲取的同時並設置新的值
58 127.0.0.1:6379> incr mycount #將計數器的值原子性的遞增1
59 (integer) 1
60 #在獲取計數器原有值的同時,並將其設置為新值,這兩個操作原子性的同時完成。
61 127.0.0.1:6379> getset mycount 0
62 "1"
63 127.0.0.1:6379> get mycount #查看設置後的結果。
64 "0"
65
66
67
68 # setex 設置過期時間
69 127.0.0.1:6379> setex mykey 10 "hello" #設置指定Key的過期時間為10秒
70 OK
71 127.0.0.1:6379> ttl mykey #通過ttl命令查看一下指定Key的剩餘存活時間(秒數)
72 (integer) 8
73
74
75 # setnx
76 127.0.0.1:6379> del mykey
77 (integer) 0
78 127.0.0.1:6379> setnx mykey 'abc' #如果key不存在,可以設置成功
79 (integer) 1
80 127.0.0.1:6379> setnx mykey 'workd' #如果key存在,設置不成功
81 (integer) 0
82 127.0.0.1:6379> get mykey
83 "abc"
84
85
86 # setrange/getrange
87 127.0.0.1:6379> set mykey "hello world"
88 OK
89 127.0.0.1:6379> get mykey
90 "hello world"
91 127.0.0.1:6379> setrange mykey 6 dd #從第6位開始替換兩位
92 (integer) 11
93 127.0.0.1:6379> get mykey
94 "hello ddrld"
95 127.0.0.1:6379> setrange mykey 20 dd #超過長度使用0代替
96 (integer) 22
97 127.0.0.1:6379> get mykey
98 "hello ddrld\x00\x00\x00\x00\x00\x00\x00\x00\x00dd"
99 127.0.0.1:6379> getrange mykey 3 12 #獲取3~12之間的內容
100 "lo ddrld\x00\x00"
101
102 # setbit/getbit
103 redis 127.0.0.1:6379> del mykey
104 (integer) 1
105 redis 127.0.0.1:6379> setbit mykey 7 1 #設置從0開始計算的第七位BIT值為1,返回原有BIT值0
106 (integer) 0
107 redis 127.0.0.1:6379> get mykey #獲取設置的結果,二進位的0000 0001的十六進位值為0x01
108 "\x01"
109 redis 127.0.0.1:6379> setbit mykey 6 1 #設置從0開始計算的第六位BIT值為1,返回原有BIT值0
110 (integer) 0
111 redis 127.0.0.1:6379> get mykey #獲取設置的結果,二進位的0000 0011的十六進位值為0x03
112 "\x03"
113 redis 127.0.0.1:6379> getbit mykey 6 #返回了指定Offset的BIT值。
114 (integer) 1
115 redis 127.0.0.1:6379> getbit mykey 10 #Offset已經超出了value的長度,因此返回0。
116 (integer) 0
117
118 # mset/mget/msetnx
119 redis 127.0.0.1:6379> mset key1 "hello" key2 "world" #批量設置了key1和key2兩個鍵。
120 OK
121 redis 127.0.0.1:6379> mget key1 key2 #批量獲取了key1和key2兩個鍵的值。
122 1) "hello"
123 2) "world"
124 #批量設置了key3和key4兩個鍵,因為之前他們並不存在,所以該命令執行成功並返回1。
125 redis 127.0.0.1:6379> msetnx key3 "stephen" key4 "liu"
126 (integer) 1
127 redis 127.0.0.1:6379> mget key3 key4
128 1) "stephen"
129 2) "liu"
130 #批量設置了key3和key5兩個鍵,但是key3已經存在,所以該命令執行失敗並返回0。
131 redis 127.0.0.1:6379> msetnx key3 "hello" key5 "world"
132 (integer) 0
133 #批量獲取key3和key5,由於key5沒有設置成功,所以返回nil。
134 redis 127.0.0.1:6379> mget key3 key5
135 1) "stephen"
136 2) (nil)
137 ```
138
139
140
141 #### 4.List類型
142
143 ##### 概述
144
145 在Redis中,List類型是按照插入順序排序的字元串鏈表。和數據結構中的普通鏈表一樣,我們可以在其頭部(left)和尾部(right)添加新的元素。在插入時,如果該鍵並不存在,Redis將為該鍵創建一個新的鏈表。與此相反,如果鏈表中所有的元素均被移除,那麼該鍵也將會被從資料庫中刪除。List中可以包含的最大元素數量是4294967295。
146 從元素插入和刪除的效率視角來看,如果我們是在鏈表的兩頭插入或刪除元素,這將會是非常高效的操作,即使鏈表中已經存儲了百萬條記錄,該操作也可以在常量時間內完成。然而需要說明的是,如果元素插入或刪除操作是作用於鏈表中間,那將會是非常低效的。相信對於有良好數據結構基礎的開發者而言,這一點並不難理解。
147
148 ```shell
149 # lpush/lpushx/lrange
150 redis-cli #在Shell提示符下啟動redis客戶端工具。
151 redis 127.0.0.1:6379> del mykey
152 (integer) 1
153 #mykey鍵並不存在,該命令會創建該鍵及與其關聯的List,之後在將參數中的values從左到右依次插入。
154 redis 127.0.0.1:6379> lpush mykey a b c d
155 (integer) 4
156 #取從位置0開始到位置2結束的3個元素。
157 redis 127.0.0.1:6379> lrange mykey 0 2
158 1) "d"
159 2) "c"
160 3) "b"
161 #取鏈表中的全部元素,其中0表示第一個元素,-1表示最後一個元素。
162 redis 127.0.0.1:6379> lrange mykey 0 -1
163 1) "d"
164 2) "c"
165 3) "b"
166 4) "a"
167 #mykey2鍵此時並不存在,因此該命令將不會進行任何操作,其返回值為0。
168 redis 127.0.0.1:6379> lpushx mykey2 e
169 (integer) 0
170 #可以看到mykey2沒有關聯任何List Value。
171 redis 127.0.0.1:6379> lrange mykey2 0 -1
172 (empty list or set)
173 #mykey鍵此時已經存在,所以該命令插入成功,並返回鏈表中當前元素的數量。
174 redis 127.0.0.1:6379> lpushx mykey e
175 (integer) 5
176 #獲取該鍵的List Value的頭部元素。
177 redis 127.0.0.1:6379> lrange mykey 0 0
178 1) "e"
179
180
181 # lpop/llen
182 redis 127.0.0.1:6379> lpush mykey a b c d
183 (integer) 4
184 redis 127.0.0.1:6379> lpop mykey
185 "d"
186 redis 127.0.0.1:6379> lpop mykey
187 "c"
188 #在執行lpop命令兩次後,鏈表頭部的兩個元素已經被彈出,此時鏈表中元素的數量是2
189 redis 127.0.0.1:6379> llen mykey
190 (integer) 2
191
192 # lrem/lset/lindex/ltrim
193 #為後面的示例準備測試數據。
194 redis 127.0.0.1:6379> lpush mykey a b c d a c
195 (integer) 6
196 #從頭部(left)向尾部(right)變數鏈表,刪除2個值等於a的元素,返回值為實際刪除的數量。
197 redis 127.0.0.1:6379> lrem mykey 2 a
198 (integer) 2
199 #看出刪除後鏈表中的全部元素。
200 redis 127.0.0.1:6379> lrange mykey 0 -1
201 1) "c"
202 2) "d"
203 3) "c"
204 4) "b"
205 #獲取索引值為1(頭部的第二個元素)的元素值。
206 redis 127.0.0.1:6379> lindex mykey 1
207 "d"
208 #將索引值為1(頭部的第二個元素)的元素值設置為新值e。
209 redis 127.0.0.1:6379> lset mykey 1 e
210 OK
211 #查看是否設置成功。
212 redis 127.0.0.1:6379> lindex mykey 1
213 "e"
214 #索引值6超過了鏈表中元素的數量,該命令返回nil。
215 redis 127.0.0.1:6379> lindex mykey 6
216 (nil)
217 #設置的索引值6超過了鏈表中元素的數量,設置失敗,該命令返回錯誤信息。
218 redis 127.0.0.1:6379> lset mykey 6 hh
219 (error) ERR index out of range
220 #僅保留索引值0到2之間的3個元素,註意第0個和第2個元素均被保留。
221 redis 127.0.0.1:6379> ltrim mykey 0 2
222 OK
223 #查看trim後的結果。
224 redis 127.0.0.1:6379> lrange mykey 0 -1
225 1) "c"
226 2) "e"
227 3) "c"
228
229 # linsert
230 #刪除該鍵便於後面的測試。
231 redis 127.0.0.1:6379> del mykey
232 (integer) 1
233 #為後面的示例準備測試數據。
234 redis 127.0.0.1:6379> lpush mykey a b c d e
235 (integer) 5
236 #在a的前面插入新元素a1。
237 redis 127.0.0.1:6379> linsert mykey before a a1
238 (integer) 6
239 #查看是否插入成功,從結果看已經插入。註意lindex的index值是0-based。
240 redis 127.0.0.1:6379> lindex mykey 0
241 "e"
242 #在e的後面插入新元素e2,從返回結果看已經插入成功。
243 redis 127.0.0.1:6379> linsert mykey after e e2
244 (integer) 7
245 #再次查看是否插入成功。
246 redis 127.0.0.1:6379> lindex mykey 1
247 "e2"
248 #在不存在的元素之前或之後插入新元素,該命令操作失敗,並返回-1。
249 redis 127.0.0.1:6379> linsert mykey after k a
250 (integer) -1
251 #為不存在的Key插入新元素,該命令操作失敗,返回0。
252 redis 127.0.0.1:6379> linsert mykey1 after a a2
253 (integer) 0
254
255 # rpush/rpushx/rpop/rpoplpush
256 #刪除該鍵,以便於後面的測試。
257 redis 127.0.0.1:6379> del mykey
258 (integer) 1
259 #從鏈表的尾部插入參數中給出的values,插入順序是從左到右依次插入。
260 redis 127.0.0.1:6379> rpush mykey a b c d
261 (integer) 4
262 #通過lrange的可以獲悉rpush在插入多值時的插入順序。
263 redis 127.0.0.1:6379> lrange mykey 0 -1
264 1) "a"
265 2) "b"
266 3) "c"
267 4) "d"
268 #該鍵已經存在並且包含4個元素,rpushx命令將執行成功,並將元素e插入到鏈表的尾部。
269 redis 127.0.0.1:6379> rpushx mykey e
270 (integer) 5
271 #通過lindex命令可以看出之前的rpushx命令確實執行成功,因為索引值為4的元素已經是新元素了。
272 redis 127.0.0.1:6379> lindex mykey 4
273 "e"
274 #由於mykey2鍵並不存在,因此該命令不會插入數據,其返回值為0。
275 redis 127.0.0.1:6379> rpushx mykey2 e
276 (integer) 0
277 #在執行rpoplpush命令前,先看一下mykey中鏈表的元素有哪些,註意他們的位置關係。
278 redis 127.0.0.1:6379> lrange mykey 0 -1
279 1) "a"
280 2) "b"
281 3) "c"
282 4) "d"
283 5) "e"
284 #將mykey的尾部元素e彈出,同時再插入到mykey2的頭部(原子性的完成這兩步操作)。
285 redis 127.0.0.1:6379> rpoplpush mykey mykey2
286 "e"
287 #通過lrange命令查看mykey在彈出尾部元素後的結果。
288 redis 127.0.0.1:6379> lrange mykey 0