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