Redis詳細(xì)介紹
Redis
NoSQL:Not Only SQL,是非關(guān)系型數(shù)據(jù)庫;
Web2.0對于上萬次的讀寫,關(guān)系型數(shù)據(jù)庫的壓力是非常大的;
因此NoSQL非關(guān)系型的數(shù)據(jù)庫應(yīng)運而生;
為什么需要NoSQL?
High performance高并發(fā)讀寫
Huge Storage海量數(shù)據(jù)的高效率存儲和訪問
High Scalability&&High Avaliability高可擴展性和高可用性
NoSQL的主流產(chǎn)品:
mongoDB,Redis,CouchDB,riak,Cassandra,neo4J等等;
NoSQL數(shù)據(jù)庫的四大分類
1. 鍵值對存儲(Key-Value)
比如:Redis可以進行鍵值對存儲數(shù)據(jù);可以快速查詢,但是存儲的數(shù)據(jù)缺少結(jié)構(gòu)化
2. 列存儲
比如:HBase就是列存儲數(shù)據(jù)庫,查找速度快,可擴展性強,功能相對于局限;
HBase是一個分布式的、面向列的開源數(shù)據(jù)庫,該技術(shù)來源于 Fay Chang 所撰寫的Google論文"Bigtable:一個結(jié)構(gòu)化數(shù)據(jù)的分布式存儲系統(tǒng)。
3. 文檔數(shù)據(jù)庫
比如:MongoDB,數(shù)據(jù)結(jié)構(gòu)要求不是特別的嚴(yán)格,查詢性能不是特別高,缺少統(tǒng)一的查詢語法;
4. 圖形數(shù)據(jù)庫
應(yīng)用于社交網(wǎng)絡(luò),利用圖結(jié)構(gòu)的相關(guān)算法;需要對整個圖進行計算才能得出結(jié)果;
NoSQL的特點:易擴展,數(shù)據(jù)庫之間沒有關(guān)系;靈活的數(shù)據(jù)模型;數(shù)據(jù)量大,高可用;
Redis
Redis是高性能的鍵值對數(shù)據(jù)庫,支持的鍵值對數(shù)據(jù)類型有:
字符串類型,散列類型,列表類型,集合類型,有序集合類型;
50個并發(fā)程序執(zhí)行10萬次請求,讀的速度:11萬次每秒,寫的速度8萬次每秒;
Redis的應(yīng)用場景:緩存,一些新聞和商品的內(nèi)容,我們都需要把這些數(shù)據(jù)放到緩存中;聊天室的在線好友列表;任務(wù)隊列秒殺,搶購等等;網(wǎng)站訪問統(tǒng)計,數(shù)據(jù)過期處理,應(yīng)用排行榜,分布式集群架構(gòu)中的session分離等等;
Redis 安裝
Window 下安裝
下載地址:https://github.com/MSOpenTech/redis/releases。
Redis 支持 32 位和 64 位。這個需要根據(jù)你系統(tǒng)平臺的實際情況選擇,這里我們下載 Redis-x64-xxx.zip壓縮包到 C 盤,解壓后,將文件夾重新命名為 redis。
注意:如果想要進入某個文件夾cmd,就直接在某個文件夾上面的框框中cmd回車即可;
例如:當(dāng)前是在redis的文件夾里面,直接cmd回車就可以;
打開一個 cmd 窗口 使用cd命令切換目錄到 C:edis 運行 redis-server.exe redis.windows.conf 。
如果想方便的話,可以把 redis 的路徑加到系統(tǒng)的環(huán)境變量里,這樣就省得再輸路徑了,后面的那個 redis.windows.conf 可以省略,如果省略,會啟用默認(rèn)的。輸入之后,會顯示如下界面:
這時候另啟一個cmd窗口,原來的不要關(guān)閉,不然就無法訪問服務(wù)端了。
切換到redis目錄下運行 redis-cli.exe -h 127.0.0.1 -p 6379 。
設(shè)置鍵值對 set myKey abc
取出鍵值對 get myKey
Linux 下安裝
下載地址:http://redis.io/download,下載最新文檔版本。
本教程使用的最新文檔版本為 2.8.17,下載并安裝:
$ wget http://download.redis.io/releases/redis-2.8.17.tar.gz
$ tar xzf redis-2.8.17.tar.gz
$cdredis-2.8.17
$make
make完后 redis-2.8.17目錄下會出現(xiàn)編譯后的redis服務(wù)程序redis-server,還有用于測試的客戶端程序redis-cli,兩個程序位于安裝目錄 src 目錄下:
下面啟動redis服務(wù).
$cdsrc
$./redis-server
注意這種方式啟動redis 使用的是默認(rèn)配置。也可以通過啟動參數(shù)告訴redis使用指定配置文件使用下面命令啟動。
$cdsrc
$./redis-server redis.conf
redis.conf是一個默認(rèn)的配置文件。我們可以根據(jù)需要使用自己的配置文件。
啟動redis服務(wù)進程后,就可以使用測試客戶端程序redis-cli和redis服務(wù)交互了。 比如:
$cdsrc
$./redis-cli
redis>setfoo bar
OK
redis>getfoo"bar"
Ubuntu 下安裝
在 Ubuntu 系統(tǒng)安裝 Redi 可以使用以下命令:
$sudoapt-getupdate
$sudoapt-getinstall redis-server
啟動 Redis
$redis-server
查看 redis 是否啟動?
$redis-cli
以上命令將打開以下終端:
redis127.0.0.1:6379>
127.0.0.1 是本機 IP ,6379 是 redis 服務(wù)端口?,F(xiàn)在我們輸入 PING 命令。
redis127.0.0.1:6379>ping
PONG
以上說明我們已經(jīng)成功安裝了redis。
Redis的安裝和使用(略)
Jedis
Jedis是redis的連接的基本操作;Redis不僅使用命令操作;基本上主流的開發(fā)語言都支持redis客戶端的操作;通過官網(wǎng)查看相應(yīng)的客戶端;https://redis.io/clients
Jedis是Redis官方首選的java客戶端開發(fā)包;Redis已經(jīng)把Jedis托管到github上面了;
Jedis的下載地址:https://github.com/xetorthio/jedis
Jedis保存數(shù)據(jù):jedis.set(“key”,”value”);
Jedis獲取數(shù)據(jù):jedis.get(“key”);
Jedis和jdbc類似,也可以使用連接池來獲取數(shù)據(jù);
比較常用是字符串String和哈希hash;
Redus是一個以key,value鍵值對的數(shù)據(jù)庫;
Key的定義:不要太長,最好不要超過1024個字節(jié),不僅會消耗內(nèi)存,還會降低查詢效率;不要太短;統(tǒng)一的命名規(guī)范;
存儲字符串String,以二進制的形式來存儲的;
存儲字符串的常用命令:
set company imooc
表示:保存數(shù)據(jù),將key的值imooc保存在company中;
get company
表示:取出數(shù)據(jù),將company中的值取出來,得到的是imooc
del company
表示: 刪除company中的值imooc,得到的是(integer)1
get company
表示:company中的值imooc已經(jīng)刪除了,此時已經(jīng)拿不到imooc了,所以得到的是(nil)
incr num
表示:首先數(shù)據(jù)庫redis中沒有num,incr num會先將num的值賦值為0,然后加1;得到的結(jié)果是(integer)1;
incr num
表示:此時數(shù)據(jù)庫redis中有了num,值為1,然后執(zhí)行incr num表示經(jīng)num的值加1,所以num的是為2;
get num
表示:獲取num的值,值為2;
decr num2
表示:數(shù)據(jù)庫redis中沒有num2的值,數(shù)據(jù)庫會先將num2的值賦值為0,然后再執(zhí)行減1的操作,結(jié)果為(integer)-1;
incrby num 5
表示:將num的值加5,如果數(shù)據(jù)庫redis中沒有num,那么執(zhí)行完incrby num 5結(jié)果是5;
decrby num 3
表示:將num的值減去3,結(jié)果為2;如果數(shù)據(jù)庫redis中之前沒有num,那么結(jié)果為-3;
append num 5
表示:在num的值后面追加字符5;如果num之前有值是3的話,那么get num的結(jié)果為”35”;那么 append num 5的結(jié)果為(integer)2,因為是字符串的長度;
Redis的數(shù)據(jù)結(jié)構(gòu)的第二種:Hash存儲
Redis中的hash可以看做是一種String的key和String的value的map容器;
非常適合存儲值對象的信息, 比如存儲用戶名密碼,姓名年齡等;如果hash中包含了很少的字段,那么這個類型的數(shù)據(jù)也將占有很少的磁盤空間;每一個hash可以存儲很多個鍵值對;
hset和hmset存值;
hset myhash username jack
說明:hset命令進行設(shè)置,key是myhash,鍵值對是username jack;表示往里面去存值,結(jié)果為:(integer)1
hset myhash age 18
說明:hset命令進行設(shè)置,key是myhash,鍵值對是age 18;表示往里面去存值,結(jié)果為:(integer)1
hmset myhash2 username rose age 21
說明:hmset可以一起設(shè)置多個key和value;key是myhash2,鍵值對是:username rose和age 21;
hget取值
hget myhash username
說明:hget取值,取的key是myhash,要取的值是username中的內(nèi)容;結(jié)果是jack
hmget myhash username age
說明:hmget獲取多個屬性的值;取的是username和age中的值,結(jié)果為:jack 18
hgetall hash
說明:hgetall表示獲取key中所有的屬性和屬性的值;這里的結(jié)果是username jack age 18
hdel刪除和del刪除
hdel myhash2 username age
說明:hdel表示刪除myhash2中的username和age的屬性,結(jié)果為(integer)2
hgetall myhash2
說明:表示獲取key為myhash2中的所有的屬性和屬性的值,結(jié)果為(empty list or set)表示是空的,獲取不到
hdel myhash2 username
說明:此時myhash2中已經(jīng)沒有值了,刪除失敗;所以結(jié)果是(integer)0
hset myhash2 username rose age 21
說明:往myhash2中存值;
del myhash2
說明:刪除myhash2中的屬性和屬性值,結(jié)果為:(integer)1
hget myhash2 username
說明:取屬性為username中的值,結(jié)果為nil,表示沒有取到,應(yīng)為之前已經(jīng)被刪除了;
hget myhash age
說明:取出age屬性中的值,結(jié)果為18;
hincrby myhash age 5
說明:hincrby表示為某個屬性增加數(shù)字;這里表示為age的屬性值增加5;
hget myhash age
說明:取出age中的屬性值,結(jié)果為23;
hexists myhash username
說明:hexists判斷myhash中的username屬性的值是否存在,存在就返回1,不存在就返回0;和結(jié)果是1;
hexists myhash password
說明:myhash中的password屬性不存在,所以返回結(jié)果是0;
hlen myhash
說明:表示獲取myhash中的屬性有幾個,結(jié)果是(integer)2
hkeys myhash
說明:獲取所有的key,結(jié)果是username age
hvals myhash
說明:獲取myhash中所有的值,結(jié)果是jack 23
Redis的數(shù)據(jù)結(jié)構(gòu)的第三種:list存儲
Redis中l(wèi)ist的數(shù)據(jù)類型是按照插入順序排序的一個字符串鏈表;和數(shù)據(jù)結(jié)構(gòu)中的普通的鏈表是一樣的;可以在頭部(左側(cè))和尾部(右側(cè))去添加新的元素,在插入的時候,如果該鍵不存在,Redis就會為該鍵創(chuàng)造一個新的鏈表;如果鏈表中的所有元素搜被移除了,那么該鍵也會被數(shù)據(jù)庫庫刪除;從元素插入和刪除的視角來看呢,如果是在鏈表的兩頭插入和刪除元素,這是非常高效的操作;如果鏈表中已經(jīng)存在了百萬條記錄,從鏈表的兩頭插入和刪除元素也是可以高效的完成;注意:如果元素的插入和刪除是作用在鏈表的中間,那么這個時候的效率會比較低;
存儲list方式
ArrayList使用數(shù)組的方式存儲數(shù)據(jù),很具索引去查詢的速度是非??斓?但是新增和刪除元素的時候需要涉及到位移操作,所以會比較慢;
LinkedList使用雙向鏈接方式,每個元素都記錄了前后元素的指針,插入和刪除數(shù)據(jù)的時候只是改變了前后元素的指針?biāo)赶蚣纯?速度都非???
雙向鏈表中添加數(shù)據(jù)
雙向鏈表中刪除數(shù)據(jù)
lpush mylist a b c
說明:lpush表示從左側(cè)向鏈表中添加數(shù)據(jù),mylist表示key,
a b c表示往鏈表中放入數(shù)據(jù),a是先進去的,在后面,b在中間,c最后進去的在最外邊兒,在最左側(cè);結(jié)果為:(integer)3
lpush mylist 1 2 3
說明:從左側(cè)向鏈表中插入數(shù)據(jù);結(jié)果為:(integer)6
rpush mylist2 a b c
rpush mylist2 1 2 3
說明:rpush表示從右側(cè)向鏈表中添加數(shù)據(jù);結(jié)果為:(integer)6
lrange mylist 0 5
說明:lrange表示查看鏈表,mylist為想要查看的鏈表,后面的為從0開始到5結(jié)束;可以從0開始計數(shù),也可以從負(fù)數(shù)開始計數(shù),如果是-1表示是鏈表尾部的元素;-2則表示倒數(shù)第二個元素;命令的結(jié)果為:3 2 1 c b a
lrange mylist2 0 -1
說明:查看mylist2鏈表中的元素:從第0個到倒數(shù)第一個,結(jié)果是:a b c 1 2 3
lrange mylist2 0 -2
說明:查看mylist2鏈表中的元素:從第0個到倒數(shù)第二個,結(jié)果是:a b c 1 2
lpop mylist
說明:lpop表示從左邊兒(頭部)彈出,mylist為key,它會返回并彈出指定的key所關(guān)聯(lián)的鏈表中的第一個元素,也就是它的頭部元素;如果您不存在就會返回nil,如果存在就會返回第一個元素;mylist中的第一個元素是3,所以3就會被彈出來,結(jié)果為:3
lrange mylist 0 -1
說明:查看鏈表mylist中的元素,從第0個到倒數(shù)第一個;結(jié)果為:2 1 c b a
因為3已經(jīng)被彈出了
rpop mylist2
說明:rpop表示從尾部(右邊)彈出;也是3杯彈出了,結(jié)果為3
lrange mylist2 0 -1
說明:查看鏈表mylist2中的元素,從第0個到倒數(shù)第一個,結(jié)果為:a b c 1 2因為2已經(jīng)被彈出了;
llen mylist
說明:llen表示獲取鏈表中元素的個數(shù);結(jié)果為5
llen mylist3
說明:因為鏈表mylist3是沒有的鏈表,所以結(jié)果為(integer)0
lpushx mylist x
說明:lpushx表示僅當(dāng)參數(shù)中指定的key存在的時候,可以向關(guān)聯(lián)的鏈表的頭部插入一個具體的值,如果key不存在就不會插入了;結(jié)果為:(integer)6
lrange mylist 0 -1
說明:查看鏈表mylist中的元素,從第0個到倒數(shù)第一個,結(jié)果為:x 2 1 c b a
lpushx mylist3 x
說明:mylist3這個key不存在,所以結(jié)果是(integer)0
rpushx mylist2 y
說明:key存在的時候,向關(guān)聯(lián)的鏈表的尾部插入一個具體的值,key不存在就不插入了;這里的key存在,結(jié)果是(integer)6
lrange mylist2 0 -1
說明:查看鏈表mylist2中的元素,從第0個到倒數(shù)第一個,結(jié)果為:a b c 1 2 y
lrem mylist
說明:lrem mylist后面跟上一個count value,該指令會刪除count個為value的元素; 如果count大于0,從頭向尾遍歷并刪除count個為value的元素;如果count小于0,從后面向前面去遍歷;如果count等于0,刪除鏈表中所有等于某個值的元素;
lpush mylist3 1 2 3
說明:往鏈表中插入1 2 3結(jié)果是(integer)3
lpush mylist3 1 2 3
說明:說明:往鏈表中插入1 2 3結(jié)果是(integer)6
lpush mylist3 1 2 3
說明:說明:往鏈表中插入1 2 3結(jié)果是(integer)9
lrange mylist3 0 -1
說明:查看mylist3鏈表里面的元素,結(jié)果為3 2 1 3 2 1 3 2 1
lrem mylist3 2 3
說明:lrem mylist3表示刪除鏈表mylist3中的2個3的元素,2大于0,從頭往尾刪除2個為3的元素,結(jié)果為(integer)2
lrange mylist3 0 -1
說明:查看mylist3中的元素;結(jié)果為:2 1 2 1 3 2 1
lrem mylist3 -2 1
說明:-2小于0,從鏈表的尾部刪除元素值為1 的元素,刪除2個,結(jié)果為(integer)2
lrange mylist3 0 -1
說明:查看鏈表中的元素,結(jié)果為:2 1 2 3 2
lrem mylist3 0 2
說明:刪除mylist3里面的所有的元素值為2的元素;結(jié)果為:(integer)3
lrange mylist3 0 -1
說明:查看鏈表中的所有的元素,結(jié)果為:1 3
lset
說明:lset設(shè)置鏈表中的某個index的腳標(biāo)的元素的值;0代表第一個元素,-1代表最后那一個元素,不存在就拋出異常;
lrange mylist 0 -1
說明:查看mylist中的所有的元素,結(jié)果為:x 2 1 c b a
lset mylist 3 mmm
說明:往鏈表mylist中的下標(biāo)(也叫腳標(biāo))為3的元素c的值設(shè)置為mmm,結(jié)果為OK
lrange mylist 0 -1
說明:查看鏈表mylist中的所有的元素的,結(jié)果為:x 2 1 mmm b a表示c被替代了;
lpush mylist4 a b c
說明:往mylist4中放入a b c元素,結(jié)果為:(integer)3
lpush mylist4 a b c
說明:往mylist4中放入a b c元素,結(jié)果為:(integer)6
lrange mylist4 0 -1
說明:查看mylist4中的所有的元素,結(jié)果為:c b a c b a
linsert mylist4 before b 11
說明:表示往b元素之前插入11的值,結(jié)果為(integer)7
注意:之前用before,之后用after
lrange mylist4 0 -1
說明:查看mylist4中所有的元素,結(jié)果為:c 11 b a c b a
lrem mylist3 0 2
說明:刪除mylist3中的所有的2
lrange mylist3 0 -1
說明:查看mylist3中的所有的元素,結(jié)果為1 3
lset
說明:lset設(shè)置鏈表中的某個index的腳標(biāo)的元素的值,0代表第一個元素,-1代表最后一個元素,腳標(biāo)不存在就會拋出異常;
lrange mylist 0 -1
說明:查看mylist鏈表中的所有的元素,結(jié)果為:x 2 1 c b a
lset mylist 3 mmm
說明:在mylist鏈表中設(shè)置第3個腳標(biāo)的值為mmm,也就是將c改成mmm
lrange mylist 0 -1
說明:查看mylist中的所有的元素,結(jié)果為:x 2 1 mmm b a
lpush mylist5 1 2 3
說明:往mylist5鏈表中放入3個元素,結(jié)果為:(integer)3
lpush mylist6 a b c
說明:往mylist6鏈表中放入3個元素,結(jié)果為:(integer)3
lrange mylist6 0 -1
說明:查看mylist6中的所有的元素,結(jié)果為c b a
rpoplpush mylist5 mylist6
說明:rpoplpush表示從mylist5鏈表(3 2 1)中從右邊開始彈出1個元素,然后從左邊放入mylist6(c b a)中,結(jié)果為1
lrange mylist5 0 -1
說明:查看mylist5鏈表中的所有的元素;結(jié)果為:3 2
lrange mylist6 0 -1
說明:查看mylist6鏈表中的所有的元素;結(jié)果為:1 c b a
redis經(jīng)常用于消息隊列的消息服務(wù),完成多個程序之間的消息交互;假設(shè)一個應(yīng)用程序正在使用lpush向鏈表中添加新的元素,通常將這樣的程序稱為生產(chǎn)者,另一個程序正在使用rpop操作,從鏈表中取出元素,稱為消費者;消費者程序在取出元素后崩潰,由于該消息已經(jīng)被取出且沒有被正常處理,我們認(rèn)為這個消息已經(jīng)丟失了,由此可能導(dǎo)致業(yè)務(wù)數(shù)據(jù)的丟失,或者導(dǎo)致業(yè)務(wù)狀態(tài)的不一致等現(xiàn)象的發(fā)生,可以通過rpop,lpush這個命令,消費者程序在主消息隊列中取出元素之后,再將它插入到一個備份的隊列中,直到消費者程序完成正常的邏輯處理后,再講消息從備份隊列中刪除,這樣的話,我們可以提供一個守護的線程,當(dāng)發(fā)現(xiàn)備份消息隊列過期的時候,可以重新將它放到主消息的隊列中,以便其他的消費者可以繼續(xù)去處理;
Redis的數(shù)據(jù)結(jié)構(gòu)的第四種:set存儲
在redis中,可以將Set類型看做成沒有排序的字符集合,和List類型一樣;可以在該類型的數(shù)據(jù)值上執(zhí)行添加,刪除,判斷某一個元素是否存在的操作;Set集合中不允許出現(xiàn)重復(fù)的元素,Set可包含的最大元素數(shù)量是4294967295;
sadd myset a b c
說明:往Set中添加元素a b c;結(jié)果為(integer)3
sadd myset a
說明:再往Set中添加元素a,這時是添加失敗的,因為a元素已經(jīng)存在了;
sadd myset 1 2 3
說明:往myset中添加元素 1 2 3,結(jié)果為(integer)3
srem myset 1 2
說明:刪除myset中的1和2元素;結(jié)果為:(integer)2
smembers myset
說明:查看myset中的元素,結(jié)果為:c b a 3
sismember myset a
說明:查看元素a是否在myset中,如果存在就返回1,不存在就返回0;
sismember myset x
說明:查看元素x是否在myset中,結(jié)果是:(integer)0
集合的差集運算sdiff key1 key2
說明:集合的差集運算,返回集合中相差的成員,而且與key的順序是有關(guān)系的;
sadd mya1 a b c
說明:往mya1中添加3個元素a b c
sadd myb1 a c 1 2
說明:往myb1中添加4個元素a c 1 2
sdiff mya1 myb1
說明:求集合mya1和myb1的差集(與順序有關(guān)),結(jié)果是:b
sadd mya2 a b c
說明:往集合mya2中添加元素a b c
sadd myb2 a c 1 2
說明:往集合myb2中添加元素a c 1 2
sinter mya2 myb2
說明:sinter為求兩個集合中都有的部分,結(jié)果為a c
sadd mya3 a b c
說明:往集合mya3中添加元素a b c
sadd myb3 a c 1 2
說明:往集合myb3中添加元素a c 1 2
sunion mya3 myb3
說明:sunion為求兩個幾個的并集;結(jié)果為:c 2 b a 1
smembers myset
說明:查看myset中的元素;結(jié)果為:c b a 3
scard myset
說明:查看myset中的元素的個數(shù),結(jié)果為(integer)4
srandmember myset
說明:srandmember隨機的返回set中的一個成員;
sdiffstore my1 mya1 myb1
說明:將兩個集合相差的元素存儲到一個新的集合,將mya1和myb1中相差的部分存儲到新的集合my1中;結(jié)果為:(integer)1
smembers my1
說明:查看集合my1的元素,結(jié)果為b;
sinterstore
說明:求兩個集合的交集,然后存儲在一個新的集合中;
sinter mya2 myb2
說明:求兩個集合的交集,結(jié)果為c a
sinterstore my2 mya2 myb2
說明:將集合mya2和myb2的交集存儲在新的集合my2中;
smembers my2
說明:查看my2集合中的元素,結(jié)果為c a
sunion mya3 myb3
說明:查看集合mya3和myb3的并集的結(jié)果;
sunionstore my3 mya3 myb3
說明:將集合mya3和myb3的并集存儲在一個新的集合my3中;
smembers my3
說明:查看my3中的所有的元素,結(jié)果為:c 2 b a 1
Set的具體使用場景:可以使用Redis的Set數(shù)據(jù)類型跟蹤一些具有唯一性的數(shù)據(jù);比如:訪問某一博客的唯一ip地址的信息,在每次訪問該博客的時候?qū)⒃L問者的ip存入到redis中,Set的數(shù)據(jù)類型就會自動保證ip地址的唯一性;還可以充分利用Set類型的服務(wù)器端聚合操作的方便高效的一些特性可以用于維護數(shù)據(jù)對象之間的一些關(guān)聯(lián)關(guān)系;比如所有購買某一個電子設(shè)備的客戶的id,被指定存儲到一個指定的Set中,而購買另外一種電子設(shè)備的id被存儲到了另外一個Set中,如果此時需要獲取有哪些客戶同時購買了這兩種商品,這個時候使用這兩個Set的交集就可以了;
Redis的數(shù)據(jù)結(jié)構(gòu)的第五種:Sorted-Set存儲
Sorted-Set不允許集合中出現(xiàn)重復(fù)的元素,Sort-Set中的每一個成員都會有一個分?jǐn)?shù)與之關(guān)聯(lián);Redis就是通過這個分?jǐn)?shù)來為集合中的成員進行從小到大的一個排序,盡管Sorted-Set中的成員必須是唯一的,但是分?jǐn)?shù)卻是可以重復(fù)的;Sorted-Set中添加,刪除,更新一個成員都是非??斓牟僮?它的時間復(fù)雜度是集合中成員的個數(shù)的對數(shù),由于Sorted-Set中的成員在集合中的位置是有序的的,即使是訪問集合中間的成員也是非常高效的;
Sorted-Set的常用命令
zadd mysort 70 zs 80 ls 90 ww
說明:zadd為添加,mysort為key,每一個元素都有一個分?jǐn)?shù),70,80,90都為分?jǐn)?shù);zs,ls,ww分別為分?jǐn)?shù)對應(yīng)的元素;返回的是存到集合中的個數(shù);結(jié)果為:(integer)3
zadd mysort 100 zs
說明:添加元素zs,如果已經(jīng)存在了元素zs,那么會用新的分?jǐn)?shù)100去替換原有的分?jǐn)?shù)70;返回結(jié)果是:(integer)0因為之前有zs元素了,所以不顯示;還是0;
zadd mysort 60 tom
說明:往mysort中新添加tom元素,結(jié)果為:(integer)1
zscore mysort zs
說明:zscort表示獲取元素的的分?jǐn)?shù),結(jié)果為100
zcard mysort
說明:zcard獲取mysort中的成員的數(shù)量,結(jié)果是(integer)4
zrem mysort tom ww
說明:zrem刪除mysort中的tom和ww元素,結(jié)果為:(integer)2
zcard mysort
說明:zcard查看mysort中的元素的個數(shù);結(jié)果為:(integer)2
zadd mysort 85 jack 95 rose
說明:往mysort中添加2個元素,jack和rose
zrange mysort 0 -1
說明:查看mysort中的所有的元素,結(jié)果為:ls jack rose zs
zrange mysort 0 -1 withscores
說明:查看mysort中所有的元素和分?jǐn)?shù);結(jié)果為:ls 80 jack 85 rose 95 zs 100;
zrevrange mysort 0 -1 withscores
說明:zrevrange從大到小查看mysort中的元素和分?jǐn)?shù);結(jié)果為:zs 100 rose 95 jack 85 ls 80
zremrangebyrank mysort 0 4
說明:按照范圍進行刪除,結(jié)果為(integer)4
zadd mysort 80 zs 90 ls 100 ws
zremrangebyscore mysort 80 100
說明:按照分?jǐn)?shù)的范圍進行刪除,刪除分?jǐn)?shù)為80到100之間的元素;結(jié)果為:(integer)3
zrange mysort 0 -1
說明:查看mysort中的所有的元素,結(jié)果為:(empty list or set)
zadd mysort 70 zs 80 ls 90 ww
zrangebyscore mysort 0 100 withscores
說明:查看mysort中分?jǐn)?shù)為0到100之間的元素,結(jié)果為:zs 70 ls 80 ww 90
zrangebyscore mysort 0 100 withscores limit 0 2
說明:查看mysort中的分?jǐn)?shù)為0到100的元素中的2個元素和分?jǐn)?shù);結(jié)果為:zs 70 ls 80
zincrby mysort 3 ls
說明:設(shè)置指定成員ls增加的分?jǐn)?shù)3;結(jié)果為:83
zscore mysort ls
說明:查看mysort中l(wèi)s元素的分?jǐn)?shù),結(jié)果為83
zcount mysort 80 90
說明:查看分?jǐn)?shù)在80到90之間的元素的個數(shù),結(jié)果為(integer)2
Sorted-Set的使用場景:使用于大型網(wǎng)絡(luò)游戲的積分排行榜;當(dāng)玩家的分?jǐn)?shù)發(fā)生變化的時候,可以使用zadd更新玩家的分?jǐn)?shù),然后通過zrange來獲取積分;Sorted-Set可以用于構(gòu)建索引數(shù)據(jù);
Keys的通用操作
keys *
說明:查看所有的key
keys my?
說明:查看以my開頭的所有key
del my1 my2 my3
說明:刪除某個指定的key;刪除my1和my2和my3的key;
exist my1
說明:查看某個key是否存在,如果存在就返回1,不存在就返回0;
get company
說明:獲取key等于company的值;比如:結(jié)果為:baidu
rename company newcompany
說明:重命名key的名字,將key的名字改為newcompany
get company
說明:獲取key等于company的值,此時的company已經(jīng)不存在了,被改名字了,所以結(jié)果是(nil)
get newcompany
說明:獲取key等于newcompany的值,結(jié)果是baidu
expire newcompany 1000
說明:設(shè)置key的過期時間,1000秒;
ttl newcompany
說明:查看key離超時還剩的時間;比如結(jié)果為:967;注意:如果沒有設(shè)置key的超時時間,就會返回-1;
type newcompany
說明:查看key的類型;比如:結(jié)果為string
Redis的特性
Redis多數(shù)據(jù)庫,Redis支持事務(wù);
一個Redis的實例可以包含多個數(shù)據(jù)庫;客戶端可以指定連接某個Redis實例的哪個數(shù)據(jù)庫;就好比是mysql中創(chuàng)建多個數(shù)據(jù)庫一樣,客戶端連接的時候可以指定連接哪個數(shù)據(jù)庫;一個Redis實例最多可以提供16個數(shù)據(jù)庫;下標(biāo)分別是熊0到15,客戶端默認(rèn)的連接是第0號數(shù)據(jù)庫;也可以通過select來選擇具體連接哪個數(shù)據(jù)庫;
select 1
說明:連接1號數(shù)據(jù)庫
keys *
說明:查看該數(shù)據(jù)庫中的所有的key,結(jié)果是(empty list or set)
select 0
說明:連接0號數(shù)據(jù)庫
keys *
說明:查看0號數(shù)據(jù)庫的所有key,結(jié)果為:mylist2 myset mya1
move myset 1
說明:將myset這個key從0號數(shù)據(jù)庫移到1號數(shù)據(jù)庫;
select 1
說明:選擇1號數(shù)據(jù)庫
keys *
說明:查看1號數(shù)據(jù)庫中的所有的key,結(jié)果為:myset;剛從0號數(shù)據(jù)庫移過來的;
select 0
說明:選擇0號數(shù)據(jù)庫;
Redis中的實現(xiàn)事務(wù)的命令:multi和exec和discard;
在事務(wù)中,所有的命令將串行化,順序執(zhí)行;在事務(wù)執(zhí)行的過程中,redis不會在為其他的數(shù)據(jù)庫客戶端提供任何的服務(wù),從而保證事務(wù)中所有的命令都被原子化,和關(guān)系型數(shù)據(jù)庫相比,在redis中,如果某一個命令執(zhí)行失敗了,后面的命令還是會被執(zhí)行;
multi可以開啟一個事務(wù);后面的命令都將會被存到隊列中,直到執(zhí)行exec命令;
exec提交事務(wù),
discard回滾
在事務(wù)開啟之前,如果客戶端和服務(wù)器之間出現(xiàn)通訊故障并導(dǎo)致網(wǎng)絡(luò)斷開;事務(wù)中的語句都將不會被服務(wù)器執(zhí)行;如果網(wǎng)絡(luò)中斷發(fā)生在客戶端執(zhí)行之后的,那么事務(wù)中的所有命令都將會被服務(wù)器執(zhí)行;
打開新的窗口
連接redis:cd /usr/local/redis
查看:ll
開啟redi的客戶端./bin/redis-cli
清空:clear
Redis的持久化
Redis所有的數(shù)據(jù)都存儲在內(nèi)存中;為了使redis在重啟之后仍然能保證數(shù)據(jù)不丟失,那么就需要將數(shù)據(jù)從內(nèi)存中同步到我們的硬盤上,這個過程我們稱之為持久化;
Redis的持久化的方式;
RDB持久化:RDB的方式是默認(rèn)支持的,不需要配置的,在指定的時間間隔內(nèi),將內(nèi)存中的數(shù)據(jù)寫到磁盤一次;可以指定30秒,50秒等等;
AOF持久化:以日志的形式記錄服務(wù)器所處理的每一個操作,在redis服務(wù)器啟動之初,AOF會讀取該文件,重新構(gòu)建數(shù)據(jù)庫,這樣保證啟動后,數(shù)據(jù)是完整的;
無持久化:通過配置禁用redis的服務(wù)器的持久化的功能;這時的redis就是一個緩存的功能;
同時使用RDB和AOF的方式:
Redis持久化的RDB的方式;
RDB方式:一旦采用了RDB方式,整個Redis數(shù)據(jù)庫將只包含一個文件,那么對于文件備份而言,是非常完美的;比如打算每個小時歸檔一次最近24小時的數(shù)據(jù),同時還要每天歸檔一次最近30天的數(shù)據(jù),可以通過RDB方式的策略,一旦系統(tǒng)出現(xiàn)災(zāi)難性的故障,可以進行非常容易的進行恢復(fù);對于災(zāi)難恢復(fù)而言,RDB是非常不錯的選擇,可以非常輕松的將一個單獨的文件壓縮后,再將它轉(zhuǎn)移到其他的存儲介質(zhì)上,可以將它拷貝走,然后恢復(fù)的時候再把它拿出來;性能最大化,對于Redis的服務(wù)進程而言,在開始持久化的時候,它唯一需要做的是分叉出一些進程,然后由子進程完成持久化的工作,這樣可以極大的避免服務(wù)器進程執(zhí)行IO的操作;相比AOF的機制,如果數(shù)據(jù)集很大,RDB的啟動效率會很高,整死RDB的優(yōu)勢,RDB的缺點:如果想要保證數(shù)據(jù)的高可用性,就是最大的限度避免數(shù)據(jù)的丟失,RDB將不是一個很好的選擇,因為系統(tǒng)一定在定時持久化之前,出現(xiàn)一些宕機的情況,還沒來得及往硬盤上面寫,數(shù)據(jù)就丟失了;比如說30秒往硬盤上面寫一次;當(dāng)?shù)搅?5秒的時候,服務(wù)器可能發(fā)生了宕機;還沒來得及往硬盤上面去寫內(nèi)容的時候;那么前25秒的數(shù)據(jù)就沒有了;RDB通過fork分叉的方式子進程來協(xié)助完成數(shù)據(jù)持久化工作的,因此當(dāng)如果數(shù)據(jù)集非常大的時候,可能會導(dǎo)致服務(wù)器會停止幾百毫秒甚至更長的時間;
RDB方式的配置:
cd /usr/local/redis
說明:比如進入到redis的路徑下,
ll
說明:查看redis中的文件,比如有redis.conf文件;
vim redis.conf
說明:打開redis.conf的配置文件;
比如:save 900 1表示:每過900秒至少有1個key發(fā)生變化,和這個時候會持久化(持久化也就是往硬盤上寫一次內(nèi)容)1次;
Redis的AOF持久化的方式
AOF機制可以帶來更高的數(shù)據(jù)安全性;
Redis提供了3種同步策略,每秒同步,每修改同步,不同步;
每秒同步:也是異步的,效率是非常高的;一旦系統(tǒng)出現(xiàn)宕機情況,這一秒鐘修改的數(shù)據(jù)就會丟失;
每修改同步:可以視為同步持久化,每一次發(fā)生數(shù)據(jù)的變化,都會被立即的記錄在磁盤中,這種效率是最低的;但是它是最安全的;
對于日志的操作采用的是append的模式,追加的模式;因此即使出現(xiàn)宕機的情況下,也不會破壞日志文件中已經(jīng)存在的內(nèi)容;然而如果本次操作只是寫入了一半的操作,就出現(xiàn)了系統(tǒng)崩潰的問題;在Redis下一次啟動之前,Redis-check-aof可以幫助解決數(shù)據(jù)一致性的問題;如果日志過大,Redis可以自動啟動重寫機制,Redis采用append的機制不斷的將修改的數(shù)據(jù)寫入到老的磁盤中,同時,redis還會創(chuàng)建一個新的文件用于記錄此期間產(chǎn)生了哪些修改命令被執(zhí)行了,因此在執(zhí)行重寫切換的時候;可以更好的保證數(shù)據(jù)的安全性;
AOF包含一個格式非常清晰的易于理解的日志文件用于記錄所有的修改操作;
對于相同的數(shù)量的數(shù)據(jù)集而言,AOF文件比RDB的文件大一些,根據(jù)同步策略不同,AOF在運行的效率上比RDB低;
AOF的配置;
vim redis.conf
說明:打開redis.conf文件;
可以看到appendonly no
因為redis默認(rèn)使用的是RDB的方式;
當(dāng)然如果想要使用AOF的方式,可以將appendonly no改為appendonly yes的方式;這個時候會產(chǎn)生一個appendonly.aof的文件;
以下是3中同步策略:
appendsync always表示每修改一次都會同步到磁盤上,
appendsync everysec表示每秒鐘往硬盤上寫一次;
appendsync no表示不同步
wq表示保存文件;
./bin/redis-cli表示連接redis客戶端;
./bin/redis-cli shutdown表示斷開redis客戶端;
shutdown表示斷開;
./bin/redis-server ./redis.conf表示重新啟動redis服務(wù)
clear表示清除屏幕
客戶端操作實例:
set name jack
set num 10
set n1 12
說明:存入一些數(shù)據(jù)
keys *
說明:查看所有的key,結(jié)果為:n1 num name
flushall
說明:清空數(shù)據(jù)庫里面的內(nèi)容;
keys *
說明:查看數(shù)據(jù)庫里面所有的key,結(jié)果為empty list or set,應(yīng)為已經(jīng)flushall了;
作者:CatherinePlans
鏈接:http://www.itdecent.cn/p/bd5f285bd825
來源:簡書
簡書著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請聯(lián)系作者獲得授權(quán)并注明出處。