一、NoSQL概述
1. 什麼是NoSQL
NoSQL(NoSQL = Not Only SQL),意即“不僅僅是SQL”,是一項全新的數據庫理念,泛指非關係型的數據庫。
(關係型數據庫<MySQL、Oracle、DB2、SQLServer>:有表,而且表與表直接存在關係<主外鍵>)
NoSQL與關係型數據庫SQL是互相彌補的……
關係型數據庫優點:對數據劃分得比較清晰(表結構和多表)
關係型數據庫缺點:進行查詢,涉及多表操作!!!(查詢效率低!!!)
非關係型數據缺點:關係描述沒有!!!!!
非關係型數據優點:查詢效率很高!!!!
2. 爲什麼要使用NoSQL
隨着互聯網web2.0網站的興起,非關係型的數據庫現在成了一個極其熱門的新領域,非關係數據庫產品的發展非常迅速。而傳統的關係數據庫在應付web2.0網站,特別是超大規模和高併發的SNS類型的web2.0純動態網站已經顯得力不從心,暴露了很多難以克服的問題,例如:
- 1、High performance - 對數據庫高併發讀寫的需求
web2.0網站要根據用戶個性化信息來實時生成動態頁面和提供動態信息,所以基本上無法使用動態頁面靜態化技術,因此數據庫併發負載非常高,往往要達到每秒上萬次讀寫請求。關係數據庫應付上萬次SQL查詢還勉強頂得住,但是應付上萬次SQL寫數據請求,硬盤IO就已經無法承受了。其實對於普通的BBS網站,往往也存在對高併發寫請求的需求,例如網站的實時統計在線用戶狀態,記錄熱門帖子的點擊次數,投票計數等,因此這是一個相當普遍的需求。
- 2、Huge Storage - 對海量數據的高效率存儲和訪問的需求
類似Facebook,twitter,Friendfeed這樣的SNS網站,每天用戶產生海量的用戶動態,以Friendfeed爲例,一個月就達到了2.5億條用戶動態,對於關係數據庫來說,在一張2.5億條記錄的表裏面進行SQL查詢,效率是極其低下乃至不可忍受的。再例如大型web網站的用戶登錄系統,例如騰訊,盛大,動輒數以億計的帳號,關係數據庫也很難應付。
- 3、High Scalability && High Availability- 對數據庫的高可擴展性和高可用性的需求
在基於web的架構當中,數據庫是最難進行橫向擴展的,當一個應用系統的用戶量和訪問量與日俱增的時候,你的數據庫卻沒有辦法像web server和app server那樣簡單的通過添加更多的硬件和服務節點來擴展性能和負載能力。對於很多需要提供24小時不間斷服務的網站來說,對數據庫系統進行升級和擴展是非常痛苦的事情,往往需要停機維護和數據遷移,爲什麼數據庫不能通過不斷的添加服務器節點來實現擴展呢?
NoSQL數據庫的產生就是爲了解決大規模數據集合多重數據種類帶來的挑戰,尤其是大數據應用難題。
3. NoSQL特點
在大數據存取上具備關係型數據庫無法比擬的性能優勢(查詢),例如:
- 易擴展
- NoSQL數據庫種類繁多,但是一個共同的特點都是去掉關係數據庫的關係型特性。數據之間無關係,這樣就非常容易擴展。也無形之間,在架構的層面上帶來了可擴展的能力。
- 大數據量,高性能
- NoSQL數據庫都具有非常高的讀寫性能,尤其在大數據量下,同樣表現優秀。這得益於它的無關係性,數據庫的結構簡單。
- 靈活的數據模型
- NoSQL無需事先爲要存儲的數據建立字段,隨時可以存儲自定義的數據格式。而在關係數據庫裏,增刪字段是一件非常麻煩的事情。如果是非常大數據量的表,增加字段簡直就是一個噩夢。這點在大數據量的Web2.0時代尤其明顯。
- 高可用
- NoSQL在不太影響性能的情況,就可以方便的實現高可用的架構。比如Cassandra,HBase模型,通過複製模型也能實現高可用。
綜上所述,NoSQL的非關係特性使其成爲了後Web2.0時代的寵兒,助力大型Web2.0網站的再次起飛,是一項全新的數據庫革命性運動。
4. 主流NoSQL產品
- NoSQL數據庫的四大分類如下:
- 鍵值(Key-Value)存儲數據庫
相關產品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB
典型應用: 內容緩存,主要用於處理大量數據的高訪問負載。 緩存、分佈式集羣
數據模型: 一系列鍵值對
優勢: 快速查詢(由它的存儲結構決定的)
劣勢: 存儲的數據缺少結構化
-
- 列存儲數據庫
相關產品:Cassandra, HBase, Riak (大數據)
典型應用:分佈式的文件系統
數據模型:以列簇式存儲,將同一列數據存在一起
優勢:查找速度快,可擴展性強,更容易進行分佈式擴展
劣勢:功能相對侷限
-
- 文檔型數據庫
相關產品:CouchDB、MongoDB 類似html
典型應用:Web應用(與Key-Value類似,Value是結構化的)
數據模型: 一系列鍵值對
優勢:數據結構要求不嚴格
劣勢: 查詢性能不高,而且缺乏統一的查詢語法
-
- 圖形(Graph)數據庫(騰訊) A B C D E
相關數據庫:Neo4J、InfoGrid、Infinite Graph
典型應用:社交網絡
數據模型:圖結構
優勢:利用圖結構相關算法。
劣勢:需要對整個圖做計算才能得出結果,不容易做分佈式的集羣方案。
二、Redis概述
1. Redis的由來
2008年,意大利的一家創業公司Merzia推出了一款基於MySQL的網站實時統計系統LLOOGG,然而沒過多久該公司的創始人 Salvatore Sanfilippo便 對MySQL的性能感到失望,於是他決定親自爲LLOOGG量身定做一個數據庫,並於2009年開發完成,這個數據庫就是Redis。 不過Salvatore Sanfilippo並不滿足只將Redis用於LLOOGG這一款產品,而是希望更多的人使用它,於是在同一年Salvatore Sanfilippo將Redis開源發佈,並開始和Redis的另一名主要的代碼貢獻者Pieter Noordhuis一起繼續着Redis的開發,直到今天。
Salvatore Sanfilippo自己也沒有想到,短短的幾年時間,Redis就擁有了龐大的用戶羣體。Hacker News在2012年發佈了一份數據庫的使用情況調查,結果顯示有近12%的公司在使用Redis。國內如新浪微博、街旁網、知乎網,國外如GitHub、Stack Overflow、Flickr等都是Redis的用戶。
2. 什麼是Redis
Redis是用C語言開發的一個開源的高性能鍵值對(key-value)數據庫。它通過提供多種鍵值數據類型來適應不同場景下的存儲需求,目前爲止Redis支持的鍵值數據類型如下:[下面的這些類型都是value的數據類型]
- 字符串類型string【最爲重要!】
- 散列類型hash
- 列表類型list
- 集合類型set
- 有序集合類型sortedset
key都是string類型的
官方提供測試數據:50個併發執行100000個請求,讀的速度是110000次/s,寫的速度是81000次/s 。數據僅供參考,根據服務器配置會有不同結果。
3. Redis常用應用場景
- Redis充當緩存(數據查詢、短連接、新聞內容、商品內容等等)。(最多使用,變化不大)
- 聊天室的在線好友列表。
- 任務隊列。(秒殺、搶購、12306等等)
- 應用排行榜。
- 網站訪問統計。
- 數據過期處理(可以精確到毫秒)
- 分佈式集羣架構中的session分離。【第一個大型項目中使用】
三、Windows版本的Redis安裝和使用
1. windows版Redis的下載
官方提倡使用Linux版的Redis,所以官網值提供了Linux版的Redis下載,我們可以從GitHub上下載window版的Redis,具體鏈接地址如下:
- 官網下載地址:http://redis.io/download
- github下載地址:https://github.com/MSOpenTech/redis/tags
2. window版Redis的目錄結構
解壓Redis壓縮包後,見到如下目錄機構:
目錄或文件 |
作用 |
redis-benchmark |
性能測試工具 |
redis-check-aof |
AOF文件修復工具 |
redis-check-dump |
RDB文件檢查工具(快照持久化文件) |
redis-cli |
命令行客戶端 |
redis-server |
redis服務器啓動命令 |
redis.windows.conf |
redis核心配置文件 |
3. window版Redis的安裝與啓動
3.1 window版Redis的安裝
window版的安裝及其簡單,解壓Redis壓縮包完成即安裝完畢
3.2 window版Redis的啓動與關閉
- 雙擊Redis目錄中redis-server.exe可以啓動redis服務,Redis服務佔用的端口是6379
- 關閉Redis的控制檯窗口就可以關閉Redis服務
3.3 window版Redis的使用
- 雙擊Redis目錄中redis-cli.exe可以啓動redis客戶端
四、Redis數據類型
1. Redis數據結構介紹
Redis是一種高級的key-value的存儲系統,其中value支持五種數據類型
字符串(string) 使用最多,和json連用
哈希(hash) 一般用於存儲JavaBean數據,但是被string+json形式完全替代
字符串列表(list) 鏈表,實時排名
字符串集合(set) 唯一性,使用環境較少
有序字符串集合(sorted set) 用於網站排名,競價排名,變化不能太快!
Key全都是字符串的!value有上述5種類型,最重要的是string!!!
而關於key的定義,需要大家注意以下幾點:
- Key不要太長,最好不要超過1024個字節,這不僅會消耗內存還會降低查找的效率
- Key不要太短,如果太短會降低key的可讀性
在項目中,定義key最好有一個統一的命名規範,越短效率越高,但是必須有意義!
2. 存儲string
-
- 概述
字符串類型是Redis中最爲基礎的數據存儲類型,它在Redis中是二進制安全的,這便意味着該類型存入和獲取的數據相同【不存在亂碼問題!】。在Redis中字符串類型的Value最多可以容納的數據長度是512M。
-
- 常用命令
2.2.1 賦值
- set key value:設定key持有指定的字符串value,如果該key存在則進行覆蓋操作。總是返回”OK”
2.2.2 取值
- get key:獲取key的value。如果與該key關聯的value不是string類型,redis將返回錯誤信息,因爲get命令只能用於獲取String value;如果該key不存在,返回(nil)。
- getset key value:先獲取該key的值,然後在設置該key的值。
2.2.3 刪除
- del key :刪除指定key 【其它類型的數據也可以刪除!!!!】
2.2.4 數值增減
- incr key:將指定的key的value原子性的遞增1.如果該key不存在,其初始值爲0,在incr之後其值爲1。如果value的值不能轉成整型,如hello,該操作將執行失敗並返回相應的錯誤信息。
- decr key:將指定的key的value原子性的遞減1.如果該key不存在,其初始值爲0,在incr之後其值爲-1。如果value的值不能轉成整型,如hello,該操作將執行失敗並返回相應的錯誤信息。
2.3 擴展命令(瞭解)
- incrby key increment:將指定的key的value原子性增加increment,如果該key不存在,器初始值爲0,在incrby之後,該值爲increment。如果該值不能轉成整型,如hello則失敗並返回錯誤信息
- decrby key decrement:將指定的key的value原子性減少decrement,如果該key不存在,器初始值爲0,在decrby之後,該值爲decrement。如果該值不能轉成整型,如hello則失敗並返回錯誤信息
- append key value:拼湊字符串。如果該key存在,則在原有的value後追加該值;如果該key不存在,則重新創建一個key/value
3. 存儲hash(瞭解,實際開發會使用string+json替換它)
3.1 概述
Redis中的Hash類型可以看成具有String Key和String Value的map容器。所以該類型非常適合於存儲值對象的信息。如username、password和age等。如果Hash中包含很少的字段,那麼該類型的數據也將僅佔用很少的磁盤空間。每一個Hash可以存儲4294967295個鍵值對。
-
- 常用命令
3.2.1 賦值
- hset key field value:爲指定的key設定field/value對(鍵值對)。
- hmset key field value [field2 value2 …]:設置key中的多個filed/value
3.2.2 取值
- hget key field:返回指定的key中的field的值
hmget key fileds:獲取key中的多個filed的值
hgetall key:獲取key中的所有filed-vaule
3.2.3 刪除
- hdel key field [field … ] :可以刪除一個或多個字段,返回值是被刪除的字段個數
\
del key :刪除整個list
3.2.4 增加數字
- hincrby key field increment:設置key中filed的值增加increment,如:age增加20
3.3 自學命令
- hexists key field:判斷指定的key中的filed是否存在
hlen key:獲取key所包含的field的數量
- hkeys key :獲得所有的key
- hvals key:獲得所有的value
3.4 爲什麼hash類型不怎麼使用了?
實際開發中會使用string類型+json數據格式的數據來取代hash類型!
4. 存儲list
4.1. 概述
在Redis中,List類型是按照插入順序排序的字符串鏈表。和數據結構中的普通鏈表一樣,我們可以在其頭部(left)和尾部(right)添加新的元素。在插入時,如果該鍵並不存在,Redis將爲該鍵創建一個新的鏈表。與此相反,如果鏈表中所有的元素均被移除,那麼該鍵也將會被從數據庫中刪除。List中可以包含的最大元素數量是4294967295。
從元素插入和刪除的效率視角來看,如果我們是在鏈表的兩頭插入或刪除元素,這將會是非常高效的操作,即使鏈表中已經存儲了百萬條記錄,該操作也可以在常量時間內完成。然而需要說明的是,如果元素插入或刪除操作是作用於鏈表中間,那將會是非常低效的。相信對於有良好數據結構基礎的開發者而言,這一點並不難理解。
- ArrayList使用數組方式存儲數據,所以根據索引查詢數據速度快,而新增或者刪除元素時需要涉及到位移操作,所以比較慢。(存放的內容越多,速度越慢)
- LinkedList使用雙向鏈接方式存儲數據,每個元素都記錄前後元素的指針,所以插入、刪除數據時只是更改前後元素的指針指向即可,速度非常快,然後通過下標查詢元素時需要從頭開始索引,所以比較慢。(插入修改快,查詢慢)
- 雙向鏈表中添加數據
雙向鏈表中刪除數據
4.2. 常用命令
4.2.1 兩端添加
- lpush key values[value1 value2…]:在指定的key所關聯的list的頭部插入所有的values,如果該key不存在,該命令在插入的之前創建一個與該key關聯的空鏈表,之後再向該鏈表的頭部插入數據。插入成功,返回元素的個數。(l:left ;push:推)
lpush mylist a b c
進行查看(使用lrange),由於它是從左側依次存放數據(類似於壓棧:先進後出)
再次運行 lpush mylist 1 2 3
- rpush key values[value1、value2…]:在該list的尾部添加元素。(r:right ;push:推)
rpush mylist 5 6 7
再進行查看:使用lrange 命令不需要指定長度,直接給起始索引位置。
4.2.2 查看列表
- lrange key start end:獲取鏈表中從start到end的元素的值,start、end從0開始計數;也可爲負數,若爲-1則表示鏈表尾部的元素,-2則表示倒數第二個,依次類推…
(lrange: l:從左側,range:範圍)
直接參看上述圖例:rpush的命令演示
4.2.3 兩端彈出(本質是刪除)
- lpop key:返回並彈出指定的key關聯的鏈表中的第一個元素,即頭部元素。如果該key不存在,返回nil;若key存在,則返回鏈表的頭部元素。
初始數據:
執行lpop命令,將鏈表的第一個元素彈出返回(之前裏面的數據會被刪除)
查看mylist中的數據
- rpop key:從尾部彈出元素。
從上面的數據可以得知最終被彈出的數據是7,在mylist保存着2 1 c b a 5 6
查看mylist中的數據
4.2.4 獲取列表中元素的個數
- llen key:返回指定的key關聯的鏈表中的元素的數量。
4.3. 擴展命令(瞭解)
- lpushx key value:僅當參數中指定的key存在時,向關聯的list的頭部插入value。如果不存在,將不進行插入。(只能插入一個數據)
- rpushx key value:在該list的尾部添加元素
- lrem key count value:刪除count個值爲value的元素,如果count大於0,從頭向尾遍歷並刪除count個值爲value的元素,如果count小於0,則從尾向頭遍歷並刪除。如果count等於0,則刪除鏈表中所有等於value的元素。
0)初始化數據
1) 從頭刪除,2個數字“3”
lrem mylist3 2 3
2) 從尾刪除,2個數字“1” -2不是代表倒數第二個元素,而是從右邊開始,刪除2個元素
lrem mylist3 -2 1
3) 刪除所有數字“2” 參數0 不代表個數,而是從0起始索引位置刪除所有
lrem mylist3 0 2
lset key index value:設置鏈表中的index的腳標的元素值value(執行的是替換該位置的數據),0代表鏈表的頭元素,-1代表鏈表的尾元素。操作鏈表的腳標不存在則拋異常。
先查看mylist的長度
設置指定角標值(最大角標是9)
linsert key before|after pivot value:在pivot元素前或者後插入value這個元素。
- rpoplpush resource destination:將鏈表中的尾部元素彈出並添加到頭部。[循環操作] resource和destination指的是2個list集合
1) 將mylist5右端彈出,壓入到mylist6左邊。
2) 將mylist6右端數據彈出,壓入到左端
4.4. 使用場景
rpoplpush的使用場景:
Redis鏈表經常會被用於消息隊列的服務,以完成多程序之間的消息交換。假設一個應用程序正在執行LPUSH操作向鏈表中左側添加新的元素,我們通常將這樣的程序稱之爲"生產者(Producer)",而另外一個應用程序正在執行RPOP操作從鏈表中右側取出元素,我們稱這樣的程序爲"消費者(Consumer)"。如果此時,消費者程序在取出消息元素後立刻崩潰,由於該消息已經被取出且沒有被正常處理,那麼我們就可以認爲該消息已經丟失,由此可能會導致業務數據丟失,或業務狀態的不一致等現象的發生。然而通過使用RPOPLPUSH命令,消費者程序在從主消息隊列中取出消息之後再將其插入到備份隊列中,直到消費者程序完成正常的處理邏輯後再將該消息從備份隊列中刪除。同時我們還可以提供一個守護進程,當發 現備份隊列中的消息過期時,可以重新將其再放回到主消息隊列中,以便其它的消費者程序繼續處理。
5.1. 概述5. 存儲set
在Redis中,我們可以將Set類型看作爲沒有排序的字符集合,和List類型一樣,我們也可以在該類型的數據值上執行添加、刪除或判斷某一元素是否存在等操作。需要說明的是,這些操作的時間複雜度爲O(1),即常量時間內完成次操作。Set可包含的最大元素數量是4294967295。
和List類型不同的是,Set集合中不允許出現重複的元素,這一點和C++標準庫中的set容器是完全相同的。換句話說,如果多次添加相同元素,Set中將僅保留該元素的一份拷貝。和List類型相比,Set類型在功能上還存在着一個非常重要的特性,即在服務器端完成多個Sets之間的聚合計算操作,如unions(並集)、intersections(交集)和differences(差集)。由於這些操作均在服務端完成,因此效率極高,而且也節省了大量的網絡IO開銷。
5.2. 常用命令
5.2.1 添加/刪除元素
- sadd key values[value1、value2…]:向set中添加數據,如果該key的值已有則不會重複添加
可以查看裏面的數據:smembers myset
- srem key members[member1、member2…]:刪除set中指定的成員(成員可以是多個)
再次查看myset中的數據
5.2.2 獲得集合中的元素
- smembers key:獲取set中所有的成員 s:set member:成員
- sismember key member:判斷參數中指定的成員是否在該set中,1表示存在,0表示不存在或者該key本身就不存在。(無論集合中有多少元素都可以極速的返回結果)
5.2.3 集合的差集運算 A-B
- sdiff key1 key2…:返回key1與key2中相差的成員,而且與key的順序有關。即返回差集。
(屬於A並且不屬於B的元素構成的集合)
5.2.4 集合的交集運算 A ∩ B
- sinter key1 key2 key3…:返回交集。
(屬於A且屬於B的元素構成的集合)
5.2.5 集合的並集運算 A ∪ B
- sunion key1 key2 key3…:返回並集。
(屬於A或者屬於B的元素構成的集合)
5.3. 擴展命令
- scard key:獲取set中成員的數量
srandmember key:隨機返回set中的一個成員
sdiffstore destination key1 key2…:將key1、key2相差的成員存儲在destination上
sinterstore destination key[key…]:將返回的交集存儲在destination上
sunionstore destination key[key…]:將返回的並集存儲在destination上
5.4. 使用場景
1.可以使用Redis的Set數據類型跟蹤一些唯一性數據,比如訪問某一博客的唯一IP地址信息。對於此場景,我們僅需在每次訪問該博客時將訪問者的IP存入Redis中,Set數據類型會自動保證IP地址的唯一性。
Stirng ip = request.getRemoteAddr()
sadd ip ip
smembers ip
scar dip //統計出ip的總數!!
jedis.sadd(“ip”,ip);
jedis.smembers(“ip”);//返回一個集合對象,然後就可以遍歷獲得所有的數據了!
2.充分利用Set類型的服務端聚合(並集、差集、交集)操作方便、高效的特性,可以用於維護數據對象之間的關聯關係。比如所有購買某一電子設備的客戶ID被存儲在一個指定的Set中,而購買另外一種電子產品的客戶ID被存儲在另外一個Set中,如果此時我們想獲取有哪些客戶同時購買了這兩種商品時,Set的intersections命令(交集:有相同元素的那一部分數據)就可以充分發揮它的方便和效率的優勢了。
myset1 c1 c3 c4 c5(iphone)
myset2 c2 c5 c6 c3(ipad)
sinter myset1 myset2 c3 c5
6. 存儲sortedset
6.1. 概述
Sorted-Set和Set類型極爲相似,它們都是字符串的集合,都不允許重複的成員出現在一個Set中。它們之間的主要差別是Sorted-Set中的每一個成員都會有一個分數(score)與之關聯,Redis正是通過分數來爲集合中的成員進行從低到高的排序(默認)。然而需要額外指出的是,儘管Sorted-Set中的成員必須是唯一的,但是分數(score)卻是可以重複的。(數據不能重複,分數可以,數據可以排序)
在Sorted-Set中添加、刪除或更新一個成員都是非常快速的操作,其時間複雜度爲集合中成員數量的對數。由於Sorted-Set中的成員在集合中的位置是有序的,因此,即便是訪問位於集合中部的成員也仍然是非常高效的。事實上,Redis所具有的這一特徵在很多其它類型的數據庫中是很難實現的,換句話說,在該點上要想達到和Redis同樣的高效,在其它數據庫中進行建模是非常困難的。
例如:遊戲排名、微博熱點話題等使用場景。
6.2. 常用命令
6.2.1 添加元素
- zadd key score member score2 member2 … :將所有成員以及該成員的分數存放到sorted-set中。如果該元素已經存在則會用新的分數替換原有的分數。返回值是新加入到集合中的元素個數,不包含之前已經存在的元素。(score可以重複,member不可以重複)
再次添加zhangsan,數據(member)不會被添加成功,分數被修改
進行查看,發現分數被修改了
zrange key start end [withscores] 查詢所有信息
6.2.2 獲得元素
- zscore key member:返回指定成員的分數
- zcard key:獲取集合中的成員數量 (set中 scard key)
之前存放了3個,然後再次添加zhangsan不成功(只是替換了分數),最後添加了Jack,所以總共只有4個成員
6.2.3 刪除元素
- zrem key member[member…]:移除集合中指定的成員,可以指定多個成員。
先刪除1個,剩餘3個,再刪除2個,剩餘1個(wangwu)
6.2.4 範圍查詢
- zrange key start end [withscores]:獲取集合中腳標爲start-end的成員,[withscores]參數表明返回的成員包含其分數。(withscores可選參數)
zrevrange key start stop [withscores]:按照元素分數從大到小的順序返回索引從start到stop之間的所有元素(包含兩端的元素)
zremrangebyrank key start stop: 按照排名範圍刪除元素(從小到大刪除)
zremrangebyscore key min max:按照分數範圍刪除元素
6.3. 擴展命令
- zrangebyscore key min max [withscores] [limit offset count]:返回分數在[min,max]的成員並按照分數從低到高排序。[withscores]:顯示分數;[limit offset count]:offset,表明從腳標爲offset的元素開始並返回count個成員。
- zincrby key increment member:設置指定成員的增加的分數。返回值是更改後的分數。
- zcount key min max:獲取分數在[min,max]之間的成員
- zrank key member:返回成員在集合中的排名。(從小到大)
- zrevrank key member:返回成員在集合中的排名。(從大到小)
6.4. 使用場景
可以用於一個大型在線遊戲的積分排行榜。每當玩家的分數發生變化時,可以執行ZADD命令更新玩家的分數(數據被覆蓋,分數被更新),此後再通過ZRANGE命令(查詢)獲取積分TOPTEN的用戶信息。當然我們也可以利用ZRANK命令通過username來獲取玩家的排行信息。最後我們將組合使用ZRANGE和ZRANK命令快速的獲取和某個玩家積分相近的其他用戶的信息。zrangebyscore key min max withscores limit offset count
五、Redis通用命令
- keys pattern:獲取所有與pattern匹配的key,返回所有與該key匹配的keys。*表示任意一個或多個字符,?表示任意一個字符
del key1 key2…:刪除指定的key
exists key:判斷該key是否存在,1代表存在,0代表不存在
rename key newkey:爲當前的key重命名
expire key :設置過期時間,單位:秒
ttl key:獲取該key所剩的超時時間,如果沒有設置超時,返回-1。如果返回-2表示超時不存在(key不存在)。
type key:獲取指定key的類型。該命令將以字符串的格式返回。 返回的字符串爲string、list、set、hash和zset,如果key不存在返回none。
六、Redis持久化
1. Redis持久化概述
Redis的高性能是由於其將所有數據都存儲在了內存中,爲了使Redis在重啓之後仍能保證數據不丟失,需要將數據從內存中同步到硬盤中,這一過程就是持久化。Redis支持兩種方式的持久化,一種是RDB方式,一種是AOF方式。可以單獨使用其中一種或將二者結合使用。
- RDB持久化(默認支持,無需配置)【快照機制】
該機制是指在指定的時間間隔內將內存中的數據集快照寫入磁盤。
- AOF持久化【日誌機制】
該機制將以日誌的形式記錄服務器所處理的每一個寫操作,在Redis服務器啓動之初會讀取該文件來重新構建數據庫,以保證啓動後數據庫中的數據是完整的。
- 無持久化
我們可以通過配置的方式禁用Redis服務器的持久化功能,這樣我們就可以將Redis視爲一個功能加強版的memcached了。
- redis可以同時使用RDB和AOF
2. RDB持久化機制
2.1 RDB持久化機制優點
- 一旦採用該方式,那麼你的整個Redis數據庫將只包含一個文件,這對於文件備份而言是非常完美的。比如,你可能打算每個小時歸檔一次最近24小時的數據,同時還要每天歸檔一次最近30天的數據。通過這樣的備份策略,一旦系統出現災難性故障,我們可以非常容易的進行恢復。
- 對於災難恢復而言,RDB是非常不錯的選擇。因爲我們可以非常輕鬆的將一個單獨的文件壓縮後再轉移到其它存儲介質上
- 性能最大化。對於Redis的服務進程而言,在開始持久化時,它唯一需要做的只是fork(分叉)出子進程,之後再由子進程完成這些持久化的工作,這樣就可以極大的避免服務進程執行IO操作了。
相比於AOF機制,如果數據集很大,RDB的啓動效率會更高
2.2 RDB持久化機制缺點
- 如果你想保證數據的高可用性,即最大限度的避免數據丟失,那麼RDB將不是一個很好的選擇。因爲系統一旦在定時持久化之前出現宕機現象,此前沒有來得及寫入磁盤的數據都將丟失。
- 由於RDB是通過fork子進程來協助完成數據持久化工作的,因此,如果當數據集較大時,可能會導致整個服務器停止服務幾百毫秒,甚至是1秒鐘
2.3 RDB持久化機制的配置
在redis.windows.conf配置文件中有如下配置:(默認不用配置,數據持久化需要在客戶端執行save命令!)
其中,上面配置的是RDB方式數據持久化時機:
關鍵字 |
時間(秒) |
key修改數量 |
解釋 |
save |
900 |
1 |
每900秒(15分鐘)至少有1個key發生變化,則dump內存快照 |
save |
300 |
10 |
每300秒(5分鐘)至少有10個key發生變化,則dump內存快照 |
save |
60 |
10000 |
每60秒(1分鐘)至少有10000個key發生變化,則dump內存快照 |
3. AOF持久化機制(日誌)
3.1 AOF持久化機制優點
- 該機制可以帶來更高的數據安全性,即數據持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事實上,每秒同步也是異步完成的,其效率也是非常高的,所差的是一旦系統出現宕機現象,那麼這一秒鐘之內修改的數據將會丟失。而每修改同步,我們可以將其視爲同步持久化,即每次發生的數據變化都會被立即記錄到磁盤中。可以預見,這種方式在效率上是最低的。至於無同步,無需多言,我想大家都能正確的理解它。
- 由於該機制對日誌文件的寫入操作採用的是append模式,因此在寫入過程中即使出現宕機現象,也不會破壞日誌文件中已經存在的內容。然而如果我們本次操作只是寫入了一半數據就出現了系統崩潰問題,不用擔心,在Redis下一次啓動之前,我們可以通過redis-check-aof工具來幫助我們解決數據一致性的問題。
- 如果日誌過大,Redis可以自動啓用rewrite機制。即Redis以append模式不斷的將修改數據寫入到老的磁盤文件中,同時Redis還會創建一個新的文件用於記錄此期間有哪些修改命令被執行。因此在進行rewrite切換時可以更好的保證數據安全性。
- AOF包含一個格式清晰、易於理解的日誌文件用於記錄所有的修改操作。事實上,我們也可以通過該文件完成數據的重建
3.2 AOF持久化機制缺點
- 對於相同數量的數據集而言,AOF文件通常要大於RDB文件
- 根據同步策略的不同,AOF在運行效率上往往會慢於RDB。總之,每秒同步策略的效率是比較高的,同步禁用策略的效率和RDB一樣高效。
- AOF持久化機制配置
3.3.1 開啓AOF持久化
修改文件:redis.windows.conf
將appendonly修改爲yes,開啓aof持久化機制,默認會在目錄下產生一個appendonly.aof文件
3.3.1 AOF持久化時機
上述配置爲aof持久化的時機,解釋如下:
關鍵字 |
持久化時機 |
解釋 |
appendfsync |
always |
每執行一次更新命令,持久化一次 |
appendfsync |
everysec |
每秒鐘持久化一次 |
appendfsync |
no |
不持久化 |
後面要想這中機制能夠順利完成,需要在啓動redis服務器端的時候加載redis.windows.conf文件!
4. 兩種機制的選擇問題
一般來說, 如果想達到足以媲美 PostgreSQL 的數據安全性, 你應該同時使用兩種持久化功能。
如果你非常關心你的數據, 但仍然可以承受數分鐘以內的數據丟失, 那麼你可以只使用 RDB 持久化。
其餘情況我個人喜好選擇AOF
七、Jedis基本使用
1. Jedis介紹
Redis不僅是使用命令來操作,現在基本上主流的語言都有客戶端支持,比如java、C、C#、C++、php、Node.js、Go等。
在官方網站裏列一些Java的客戶端,有Jedis、Redisson、Jredis、JDBC-Redis、等其中官方推薦使用Jedis和Redisson。 在企業中用的最多的就是Jedis,下面我們就重點學習下Jedis。
Jedis同樣也是託管在github上,地址:https://github.com/xetorthio/jedis
使用Jedis操作redis需要導入jar包如下:
2. Jedis基本操作
2.1 Jedis官方文檔查詢方式
- 官方文檔地址:http://xetorthio.github.io/jedis/
- 官方文檔查詢方式:
2.2 Jedis常用API
方法 |
解釋 |
new Jedis(host, port) |
創建jedis對象,參數host是redis服務器地址,參數port是redis服務端口 |
set(key,value) |
設置字符串類型的數據 |
get(key) |
獲得字符串類型的數據 |
hset(key,field,value) |
設置哈希類型的數據 |
hget(key,field) |
獲得哈希類型的數據 |
lpush(key,values) |
設置列表類型的數據 |
lpop(key) |
列表左面彈棧 |
rpop(key) |
列表右面彈棧 |
del(key) |
刪除指定的key |
2.3 Jedis基本操作代碼演示
要想讓數據持久化到磁盤,可以在設置值之後調用jedis.save()方法!
3. Jedis連接池的使用
2.1 Jedis連接池的介紹
jedis連接資源的創建與銷燬是很消耗程序性能,所以jedis爲我們提供了jedis的池化技術,jedisPool在創建時初始化一些連接資源存儲到連接池中,使用jedis連接資源時不需要創建,而是從連接池中獲取一個資源進行redis的操作,使用完畢後,不需要銷燬該jedis連接資源,而是將該資源歸還給連接池,供其他請求使用。
2.2 Jedis官方文檔查詢方式
2.3 Jedis連接池代碼演示(JedisPool)
2.4 Jedis連接池工具類(JedisUtils)
2.4.1 配置文件(jedis.properties)
jedis.host=localhost
jedis.port=6379
jedis.maxTotal=30
jedis.maxIdle=10
2.4.2 工具類
2.4.3 工具類測試類