[Redis]Redis 概述及基本使用規范.
1 nosql的簡介
1.1 nosql簡介
隨着互聯網Web2.0網站的興起,傳統的關系數據庫在應付Web2.0網站,特別是超大規模和高並發的SNS類型的Web2.0純動態網站已經顯得力不從心,暴露了很多難以克服的問題,如:
1.1.1 對數據庫高並發讀寫的需求
網站要根據用戶個性化信息來實時生成動態頁面和提供動態信息,所以基本上無法使用動態頁面靜態化技術,因此數據庫並發負載非常高,往往要達到每秒上萬次讀寫請求。關系數據庫應付上萬次SQL查詢還勉強頂得住,但是應付上千萬次SQL寫數據請求,硬盤IO就已經無法承受了。
1.1.2 對海量數據的高效率存儲和訪問的需求
對於大型的SNS網站,每天用戶產生海量的用戶動態,以國外的Friendfeed為例,一個月就達到了2.5億條用戶動態,對於關系數據庫來說,在一張2.5億條記錄的表里面進行SQL查詢,效率是極其低下乃至不可忍受的。
1.1.3 對數據庫的高可擴展性和高可用性的需求
在基於Web的架構當中,數據庫是最難進行橫向擴展的,當一個應用系統的用戶量和訪問量與日俱增的時候,你的數據庫卻沒有辦法像Web服務器和應用服務器那樣簡單的通過添加更多的硬件和服務節點來擴展性能和負載能力。對於很多需要提供7*24小時不間斷服務的網站來說,對數據庫系統進行升級和擴展是非常痛苦的事情,往往需要停機維護和數據遷移,為什么數據庫不能通過不斷的添加服務器節點來實現擴展呢?
在上面提到的“三高”的需求面前,關系數據庫遇到了難以克服的障礙,而對於Web2.0網站來說,關系數據庫的很多主要特性卻往往無用武之地,例如:
(1)數據庫事務一致性需求
很多Web實時系統並不要求嚴格的數據庫事務,對讀一致性的要求很低,有些場合對寫一致性要求也不高。因此數據庫事務管理成了數據庫高負載下一個沉重的負擔。
(2)數據庫的寫實時性和讀實時性需求
對關系數據庫來說,插入一條數據之后立刻查詢,是肯定可以讀出來這條數據的。並不要求這么高的實時性。
(3)對復雜的SQL查詢,特別是多表關聯查詢的需求
任何大數據量的Web系統,都非常忌諱多個大表的關聯查詢,以及復雜的數據分析類型的復雜SQL報表查詢,特別是SNS類型的網站,從需求以及產品設計角度,就避免了這種情況的產生。往往更多的只是單表的主鍵查詢,以及單表的簡單條件分頁查詢,SQL的功能被極大的弱化了。
因此,關系數據庫在這些越來越多的應用場景下顯得不那么合適了,為了解決這類問題的非關系數據庫應運而生。NoSQL 是非關系型數據存儲的廣義定義。它打破了長久以來關系型數據庫與ACID理論大一統的局面。NoSQL 數據存儲不需要固定的表結構(例如以鍵值對存儲,它的結構不固定,每一個元組可以有不一樣的字段,每個元組可以根據需要增加一些自己的鍵值對,這樣就不會局限於固定的結構,可以減少一些時間和空間的開銷),通常也不存在連接操作。
1.2 NoSQL無與倫比的特點
在大數據存取上具備關系型數據庫無法比擬的性能優勢,例如:
1.2.1 易擴展
NoSQL數據庫種類繁多,但是一個共同的特點都是去掉關系數據庫的關系型特性。數據之間無關系,這樣就非常容易擴展。也無形之間,在架構的層面上帶來了可擴展的能力。
1.2.2 大數據量,高性能
NoSQL數據庫都具有非常高的讀寫性能,尤其在大數據量下,同樣表現優秀。這得益於它的無關系性,數據庫的結構簡單。
1.2.3 靈活的數據模型
NoSQL無需事先為要存儲的數據建立字段,隨時可以存儲自定義的數據格式。而在關系數據庫里,增刪字段是一件非常麻煩的事情。如果是非常大數據量的表,增加字段簡直就是一個噩夢。這點在大數據量的Web2.0時代尤其明顯。
1.2.4 高可用
NoSQL在不太影響性能的情況,就可以方便的實現高可用的架構。比如Cassandra,HBase模型,通過復制模型也能實現高可用。
綜上所述,NoSQL的非關系特性使其成為了后Web2.0時代的寵兒,助力大型Web2.0網站的再次起飛,是一項全新的數據庫革命性運動。
1.3 redis簡介
隨着應用對高性能需求的增加,NoSQL逐漸在各大名企的系統架構中生根發芽。時至今日,涌現出的NoSQL產品已經有很多種了,例如Membase、MongoDB、Apache Cassandra、CouchDB等。不過,在國內外互聯網巨頭例如社交巨頭新浪微博、傳媒巨頭Viacom及圖片分享領域佼佼者Pinterest等名企都不約而同地采用了Redis作為其NoSQL數據庫的選擇,到底Redis是何方神聖呢?能讓如此多的名企為它而痴狂。
按照官方的說法,Redis是一個開源的,使用C語言編寫,面向“鍵/值”(Key/Value)對類型數據的分布式NoSQL數據庫系統,特點是高性能,持久存儲,適應高並發的應用場景。因此,可以說Redis純粹為應用而產生,它是一個高性能的key-value數據庫,並且還提供了多種語言的API(包括我們的大C#)。那么,也許我們會問:到底性能如何呢?以下是官方的bench-mark數據:
測試完成了50個並發執行100000個請求。
設置和獲取的值是一個256字節字符串。
Linux box是運行Linux 2.6,這是X3320 Xeon 2.5 ghz。
文本執行使用loopback接口(127.0.0.1)。
結果:讀的速度是110000次/s,寫的速度是81000次/s 。(當然不同的服務器配置性能也有所不同)。
和Memcached類似,Redis支持存儲的value類型相對更多,包括string(字符串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,Redis支持各種不同方式的排序。與Memcached一樣,為了保證效率,數據都是緩存在內存中。區別的是Redis會周期性的把更新的數據寫入磁盤或者把修改操作寫入追加的記錄文件,並且在此基礎上實現了master-slave(主從)同步(數據可以從主服務器向任意數量的從服務器上同步,從服務器可以是關聯其他從服務器的主服務器。)。
因此,Redis的出現,很大程度補償了Memcached這類key/value存儲的不足,在部分場合可以對關系數據庫起到很好的補充作用。
1.4 redis是什么
redis是一個開源的、使用C語言編寫的、支持網絡交互的、可基於內存也可持久化的Key-Value數據庫。
redis的作者,Salvatore Sanfilippo,來自意大利的西西里島,現在居住在卡塔尼亞。目前供職於Pivotal公司。他使用的網名是antirez,如果你有興趣,可以去他的博客逛逛,地址是antirez.com,他的github地址是http://github.com/antirez。
2 CentOS下安裝redis
步驟:
1、 將Windows下下載的壓縮文件上傳到Linux下。我們可以通過filezilla等FTP軟件上傳,這里通過secureCRT進行上傳。步驟如下:
l alt + p
l put c:/redis-2.6.16.tar.gz
l 完成上傳
2、 解壓文件
l tar –zxvf redis-2.6.16.tar.gz
3、 編譯redis
l 進入解壓文件夾,cd redis-2.6.16
l 執行make[編譯,將.c文件編譯為.o文件]
4、 安裝
l make PREFIX=/usr/local/redis install
l 安裝完后,在/usr/local/redis/bin下有幾個可執行文件
redis-benchmark ----性能測試工具
redis-check-aof ----檢查修復aof文件 appendonly file
redis-check-dump ----檢查快照持久化文件
redis-cli ----命令行客戶端
redis-server ----redis服務器啟動命令
5、 copy文件
redis啟動需要一個配置文件:cp redis.conf /usr/local/redis
6、 啟動redis /usr/local/redis/bin… 查看該進程: ps -ef | grep redis 結束該進程:kill -9 pid(進程號)
命令:bin/redis-server redis.conf,這種方式又稱為前台啟動。后台啟動可修redis.conf文件,daemonize no-àyes即可。
3 redis的數據結構
redis是一種高級的key-value的存儲系統,其中value支持五種數據類型。
1、 字符串(String)
2、 字符串列表(lists)
3、 字符串集合(sets)
4、 有序字符串集合(sorted sets)
5、 哈希(hashs)
而關於key的定義呢,需要大家注意的幾點:
1、 key不要太長,最好不要操作1024個字節,這不僅會消耗內存還會降低查找效率
2、 key不要太短,如果太短會降低key的可讀性
3、 在項目中,key最好有一個統一的命名規范
3.1 存儲string
3.1.1 概述
字符串類型是Redis中最為基礎的數據存儲類型,它在Redis中是二進制安全的,這便意味着該類型可以接受任何格式的數據,如JPEG圖像數據或Json對象描述信息等。在Redis中字符串類型的Value最多可以容納的數據長度是512M。
3.1.2 常用命令
l set key value:設定key持有指定的字符串value,如果該key存在則進行覆蓋操作。總是返回”OK”
l get key:獲取key的value。如果與該key關聯的value不是String類型,redis將返回錯誤信息,因為get命令只能用於獲取String value;如果該key不存在,返回null。
l getset key value:先獲取該key的值,然后在設置該key的值。
l incr key:將指定的key的value原子性的遞增1.如果該key不存在,其初始值為0,在incr之后其值為1。如果value的值不能轉成整型,如hello,該操作將執行失敗並返回相應的錯誤信息。
l decr key:將指定的key的value原子性的遞減1.如果該key不存在,其初始值為0,在incr之后其值為-1。如果value的值不能轉成整型,如hello,該操作將執行失敗並返回相應的錯誤信息。
l incrby key increment:將指定的key的value原子性增加increment,如果該key不存在,器初始值為0,在incrby之后,該值為increment。如果該值不能轉成整型,如hello則失敗並返回錯誤信息
l decrby key decrement:將指定的key的value原子性減少decrement,如果該key不存在,器初始值為0,在decrby之后,該值為decrement。如果該值不能轉成整型,如hello則失敗並返回錯誤信息
l append key value:如果該key存在,則在原有的value后追加該值;如果該key不存在,則重新創建一個key/value
3.2 存儲list
3.2.1 概述
在Redis中,List類型是按照插入順序排序的字符串鏈表。和數據結構中的普通鏈表一樣,我們可以在其頭部(left)和尾部(right)添加新的元素。在插入時,如果該鍵並不存在,Redis將為該鍵創建一個新的鏈表。與此相反,如果鏈表中所有的元素均被移除,那么該鍵也將會被從數據庫中刪除。List中可以包含的最大元素數量是4294967295。
從元素插入和刪除的效率視角來看,如果我們是在鏈表的兩頭插入或刪除元素,這將會是非常高效的操作,即使鏈表中已經存儲了百萬條記錄,該操作也可以在常量時間內完成。然而需要說明的是,如果元素插入或刪除操作是作用於鏈表中間,那將會是非常低效的。相信對於有良好數據結構基礎的開發者而言,這一點並不難理解。
1、 ArrayList使用數組方式存儲數據,所以根據索引查詢數據速度快,而新增或者刪除元素時需要設計到位移操作,所以比較慢。
2、 LinkedList使用雙向鏈接方式存儲數據,每個元素都記錄前后元素的指針,所以插入、刪除數據時只是更改前后元素的指針指向即可,速度非常快,然后通過下標查詢元素時需要從頭開始索引,所以比較慢。
3、 雙向鏈表中添加數據
4、 雙向鏈表中刪除數據
5、 時間復雜度
3.2.2 常用命令
l lpush key values[value1 value2…]:在指定的key所關聯的list的頭部插入所有的values,如果該key不存在,該命令在插入的之前創建一個與該key關聯的空鏈表,之后再向該鏈表的頭部插入數據。插入成功,返回元素的個數。
l lpushx key value:僅當參數中指定的key存在時(如果與key管理的list中沒有值時,則該key是不存在的)在指定的key所關聯的list的頭部插入value。
l lrange key start end:獲取鏈表中從start到end的元素的值,start、end可為負數,若為-1則表示鏈表尾部的元素,-2則表示倒數第二個,依次類推…
l lpop key:返回並彈出指定的key關聯的鏈表中的第一個元素,即頭部元素。如果該key不存在,返回nil;若key存在,則返回鏈表的頭部元素。
l llen key:返回指定的key關聯的鏈表中的元素的數量。
l lrem key count value:刪除count個值為value的元素,如果count大於0,從頭向尾遍歷並刪除count個值為value的元素,如果count小於0,則從尾向頭遍歷並刪除。如果count等於0,則刪除鏈表中所有等於value的元素。
l lset key index value:設置鏈表中的index的腳標的元素值,0代表鏈表的頭元素,-1代表鏈表的尾元素。操作鏈表的腳標則放回錯誤信息。
l linsert key before|after pivot value:在pivot元素前或者后插入value這個元素。
l rpush key values[value1、value2…]:在該list的尾部添加元素。
l rpushx key value’:在該list的尾部添加元素
l rpop key:從尾部彈出元素。
l rpoplpush resource destination:將鏈表中的尾部元素彈出並添加到頭部。[循環操作]
3.2.3 使用場景
rpoplpush的使用場景:
Redis鏈表經常會被用於消息隊列的服務,以完成多程序之間的消息交換。假設一個應用程序正在執行LPUSH操作向鏈表中添加新的元素,我們通常將這樣的程序稱之為"生產者(Producer)",而另外一個應用程序正在執行RPOP操作從鏈表中取出元素,我們稱這樣的程序為"消費者(Consumer)"。如果此時,消費者程序在取出消息元素后立刻崩潰,由於該消息已經被取出且沒有被正常處理,那么我們就可以認為該消息已經丟失,由此可能會導致業務數據丟失,或業務狀態的不一致等現象的發生。然而通過使用RPOPLPUSH命令,消費者程序在從主消息隊列中取出消息之后再將其插入到備份隊列中,直到消費者程序完成正常的處理邏輯后再將該消息從備份隊列中刪除。同時我們還可以提供一個守護進程,當發現備份隊列中的消息過期時,可以重新將其再放回到主消息隊列中,以便其它的消費者程序繼續處理。
3.3 存儲hash
3.3.1 概述
Redis中的Hashes類型可以看成具有String Key和String Value的map容器。所以該類型非常適合於存儲值對象的信息。如Username、Password和Age等。如果Hash中包含很少的字段,那么該類型的數據也將僅占用很少的磁盤空間。每一個Hash可以存儲4294967295個鍵值對。
3.3.2 常用命令
l hset key field value:為指定的key設定field/value對(鍵值對)。
l hget key field:返回指定的key中的field的值
l hexists key field:判斷指定的key中的filed是否存在
l hlen key:獲取key所包含的field的數量
l hincrby key field increment:設置key中filed的值增加increment,如:age增加20
l hmset key fields:設置key中的多個filed/value
l hmget key fileds:獲取key中的多個filed的值
3.4 存儲set
3.4.1 概述
在Redis中,我們可以將Set類型看作為沒有排序的字符集合,和List類型一樣,我們也可以在該類型的數據值上執行添加、刪除或判斷某一元素是否存在等操作。需要說明的是,這些操作的時間復雜度為O(1),即常量時間內完成次操作。Set可包含的最大元素數量是4294967295。
和List類型不同的是,Set集合中不允許出現重復的元素,這一點和C++標准庫中的set容器是完全相同的。換句話說,如果多次添加相同元素,Set中將僅保留該元素的一份拷貝。和List類型相比,Set類型在功能上還存在着一個非常重要的特性,即在服務器端完成多個Sets之間的聚合計算操作,如unions、intersections和differences。由於這些操作均在服務端完成,因此效率極高,而且也節省了大量的網絡IO開銷。
3.4.2 常用命令
l sad key values[value1、value2…]:向set中添加數據,如果該key的值已有則不會重復添加
l smembers key:獲取set中所有的成員
l scard key:獲取set中成員的數量
l sismember key member:判斷參數中指定的成員是否在該set中,1表示存在,0表示不存在或者該key本身就不存在
l srem key members[member1、member2…]:刪除set中指定的成員
l srandmember key:隨機返回set中的一個成員
l sdiff key[sdiff key1 key2…]:返回key1與key2中相差的成員,而且與key的順序有關。即返回差集。
l sdiffstore destination key[key1、key2…]:將key1、key2相差的成員存儲在destination上
l sinter key[key1,key2…]:返回交集。
l sinterstore destination key[key…]:將返回的交集存儲在destination上
l sunion key[key1、key2…]:返回並集。
l sunionstore destination key[key…]:將返回的並集存儲在destination上
3.4.3 使用場景
1、可以使用Redis的Set數據類型跟蹤一些唯一性數據,比如訪問某一博客的唯一IP地址信息。對於此場景,我們僅需在每次訪問該博客時將訪問者的IP存入Redis中,Set數據類型會自動保證IP地址的唯一性。
2、充分利用Set類型的服務端聚合操作方便、高效的特性,可以用於維護數據對象之間的關聯關系。比如所有購買某一電子設備的客戶ID被存儲在一個指定的Set中,而購買另外一種電子產品的客戶ID被存儲在另外一個Set中,如果此時我們想獲取有哪些客戶同時購買了這兩種商品時,Set的intersections命令就可以充分發揮它的方便和效率的優勢了。
3.5 存儲sortedset
3.5.1 概述
Sorted-Sets和Sets類型極為相似,它們都是字符串的集合,都不允許重復的成員出現在一個Set中。它們之間的主要差別是Sorted-Sets中的每一個成員都會有一個分數(score)與之關聯,Redis正是通過分數來為集合中的成員進行從小到大的排序。然而需要額外指出的是,盡管Sorted-Sets中的成員必須是唯一的,但是分數(score)卻是可以重復的。
在Sorted-Set中添加、刪除或更新一個成員都是非常快速的操作,其時間復雜度為集合中成員數量的對數。由於Sorted-Sets中的成員在集合中的位置是有序的,因此,即便是訪問位於集合中部的成員也仍然是非常高效的。事實上,Redis所具有的這一特征在很多其它類型的數據庫中是很難實現的,換句話說,在該點上要想達到和Redis同樣的高效,在其它數據庫中進行建模是非常困難的。
例如:游戲排名、微博熱點話題等使用場景。
3.5.2 常用命令
l zadd key score member score2 member2 … :將所有成員以及該成員的分數存放到sorted-set中
l zcard key:獲取集合中的成員數量
l zcount key min max:獲取分數在[min,max]之間的成員
l zincrby key increment member:設置指定成員的增加的分數。
l zrange key start end [withscores]:獲取集合中腳標為start-end的成員,[withscores]參數表明返回的成員包含其分數。
l zrangebyscore key min max [withscores] [limit offset count]:返回分數在[min,max]的成員並按照分數從低到高排序。[withscores]:顯示分數;[limit offset count]:offset,表明從腳標為offset的元素開始並返回count個成員。
l zrank key member:返回成員在集合中的位置。
l zrem key member[member…]:移除集合中指定的成員,可以指定多個成員。
l zscore key member:返回指定成員的分數
3.5.3 使用場景
1、可以用於一個大型在線游戲的積分排行榜。每當玩家的分數發生變化時,可以執行ZADD命令更新玩家的分數,此后再通過ZRANGE命令獲取積分TOPTEN的用戶信息。當然我們也可以利用ZRANK命令通過username來獲取玩家的排行信息。最后我們將組合使用ZRANGE和ZRANK命令快速的獲取和某個玩家積分相近的其他用戶的信息。
2、Sorted-Sets類型還可用於構建索引數據。
4 key的通用操作
l keys pattern:獲取所有與pattern匹配的key,返回所有與該key匹配的keys。*表示任意一個或多個字符,?表示任意字符,[abc]表示方括號中任意一個字母
l del key[key1、key2…]:刪除指定的key
l exists key:判斷該key是否存在,1代表存在,0代表不存在
l rename key newkey:為當前的key重命名
l ttl key:獲取該key所剩的超時時間,如果不存在或沒有超時設置,返回-1
l type key:獲取指定key的類型。該命令將以字符串的格式返回。返回的字符串為string、list、set、hash和zset,如果key不存在返回none。
5 redis其他特性
5.1 消息訂閱與發布
subscribe channel:訂閱頻道,例:subscribe mychat,訂閱mychat這個頻道
psubscribe channel*:批量訂閱頻道,例:psubscribe s*,訂閱以”s”開頭的頻道
publish channel content:在指定的頻道中發布消息,如 publish mychat ‘today is a newday’
5.2 多數據庫
5.2.1 概念
一個Redis實例可以包括多個數據庫,客戶端可以指定連接某個redis實例的哪個數據庫,就好比一個mysql中創建多個數據庫,客戶端連接時指定連接哪個數據庫。
一個redis實例最多可提供16個數據庫,下標從0到15,客戶端默認連接第0號數據庫,也可以通過select選擇連接哪個數據庫,如下連接1號庫:
連接0號數據庫:
5.2.2 將newkey移植到1號庫
move newkey 1:將當前庫的key移植到1號庫中
5.2.3 注意問題
在0號數據庫存儲數據,在1號數據庫執行清空數據命令卻把0號數據庫的數據給清空了:
建議:不同的應用系統要使用不同的redis實例而不是使用同一個redis實例下的不同數據庫。
5.3 redis事務
5.3.1 概念
和眾多其它數據庫一樣,Redis作為NoSQL數據庫也同樣提供了事務機制。在Redis中,MULTI/EXEC/DISCARD/WATCH這四個命令是我們實現事務的基石。
5.3.2 redis事務特征
1、 在事務中的所有命令都將會被串行化的順序執行,事務執行期間,Redis不會再為其它客戶端的請求提供任何服務,從而保證了事物中的所有命令被原子的執行
2、 和關系型數據庫中的事務相比,在Redis事務中如果有某一條命令執行失敗,其后的命令仍然會被繼續執行。
3、 我們可以通過MULTI命令開啟一個事務,有關系型數據庫開發經驗的人可以將其理解為"BEGIN TRANSACTION"語句。在該語句之后執行的命令都將被視為事務之內的操作,最后我們可以通過執行EXEC/DISCARD命令來提交/回滾該事務內的所有操作。這兩個Redis命令可被視為等同於關系型數據庫中的COMMIT/ROLLBACK語句。
4、 在事務開啟之前,如果客戶端與服務器之間出現通訊故障並導致網絡斷開,其后所有待執行的語句都將不會被服務器執行。然而如果網絡中斷事件是發生在客戶端執行EXEC命令之后,那么該事務中的所有命令都會被服務器執行。
5、 當使用Append-Only模式時,Redis會通過調用系統函數write將該事務內的所有寫操作在本次調用中全部寫入磁盤。然而如果在寫入的過程中出現系統崩潰,如電源故障導致的宕機,那么此時也許只有部分數據被寫入到磁盤,而另外一部分數據卻已經丟失。Redis服務器會在重新啟動時執行一系列必要的一致性檢測,一旦發現類似問題,就會立即退出並給出相應的錯誤提示。此時,我們就要充分利用Redis工具包中提供的redis-check-aof工具,該工具可以幫助我們定位到數據不一致的錯誤,並將已經寫入的部分數據進行回滾。修復之后我們就可以再次重新啟動Redis服務器了。
5.3.3 命令解釋
l multi:開啟事務用於標記事務的開始,其后執行的命令都將被存入命令隊列,直到執行EXEC時,這些命令才會被原子的執行,類似與關系型數據庫中的:begin transaction
l exec:提交事務,類似與關系型數據庫中的:commit
l discard:事務回滾,類似與關系型數據庫中的:rollback
5.3.4 測試
5.3.4.1 正常執行事務
5.3.4.2 失敗命令
5.3.4.3 回滾
6 jedis使用
同之前我們講過的solrj一樣,通過jedis提供的API我們連接redis服務並對其數據進行維護。而且其API與命令基本一致。
6.1 導入jar包
6.2 代碼
7 redis運維知識
7.1 redis持久化
1、 RDB持久化(默認支持,無需配置)
該機制是指在指定的時間間隔內將內存中的數據集快照寫入磁盤。
2、 AOF持久化
該機制將以日志的形式記錄服務器所處理的每一個寫操作,在Redis服務器啟動之初會讀取該文件來重新構建數據庫,以保證啟動后數據庫中的數據是完整的。
3、 無持久化
我們可以通過配置的方式禁用Redis服務器的持久化功能,這樣我們就可以將Redis視為一個功能加強版的memcached了。
4、 redis同時使用RDB和AOF
7.1.1 RDB
7.1.1.1 優勢
1、 一旦采用該方式,那么你的整個Redis數據庫將只包含一個文件,這對於文件備份而言是非常完美的。比如,你可能打算每個小時歸檔一次最近24小時的數據,同時還要每天歸檔一次最近30天的數據。通過這樣的備份策略,一旦系統出現災難性故障,我們可以非常容易的進行恢復。
2、 對於災難恢復而言,RDB是非常不錯的選擇。因為我們可以非常輕松的將一個單獨的文件壓縮后再轉移到其它存儲介質上
3、 性能最大化。對於Redis的服務進程而言,在開始持久化時,它唯一需要做的只是fork出子進程,之后再由子進程完成這些持久化的工作,這樣就可以極大的避免服務進程執行IO操作了。
4、 相比於AOF機制,如果數據集很大,RDB的啟動效率會更高。
7.1.1.2 劣勢
1、 如果你想保證數據的高可用性,即最大限度的避免數據丟失,那么RDB將不是一個很好的選擇。因為系統一旦在定時持久化之前出現宕機現象,此前沒有來得及寫入磁盤的數據都將丟失。
2、 由於RDB是通過fork子進程來協助完成數據持久化工作的,因此,如果當數據集較大時,可能會導致整個服務器停止服務幾百毫秒,甚至是1秒鍾
7.1.1.3 配置說明Snapshotting
l save 900 1 #每900秒(15分鍾)至少有1個key發生變化,則dump內存快照。
l save 300 10 #每300秒(5分鍾)至少有10個key發生變化,則dump內存快照
l save 60 10000 #每60秒(1分鍾)至少有10000個key發生變化,則dump內存快照
7.1.2 AOF
7.1.2.1 優勢
1、 該機制可以帶來更高的數據安全性,即數據持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事實上,每秒同步也是異步完成的,其效率也是非常高的,所差的是一旦系統出現宕機現象,那么這一秒鍾之內修改的數據將會丟失。而每修改同步,我們可以將其視為同步持久化,即每次發生的數據變化都會被立即記錄到磁盤中。可以預見,這種方式在效率上是最低的。至於無同步,無需多言,我想大家都能正確的理解它。
2、 由於該機制對日志文件的寫入操作采用的是append模式,因此在寫入過程中即使出現宕機現象,也不會破壞日志文件中已經存在的內容。然而如果我們本次操作只是寫入了一半數據就出現了系統崩潰問題,不用擔心,在Redis下一次啟動之前,我們可以通過redis-check-aof工具來幫助我們解決數據一致性的問題。
3、 如果日志過大,Redis可以自動啟用rewrite機制。即Redis以append模式不斷的將修改數據寫入到老的磁盤文件中,同時Redis還會創建一個新的文件用於記錄此期間有哪些修改命令被執行。因此在進行rewrite切換時可以更好的保證數據安全性。
4、 AOF包含一個格式清晰、易於理解的日志文件用於記錄所有的修改操作。事實上,我們也可以通過該文件完成數據的重建。
7.1.2.2 劣勢
1、 對於相同數量的數據集而言,AOF文件通常要大於RDB文件
2、 根據同步策略的不同,AOF在運行效率上往往會慢於RDB。總之,每秒同步策略的效率是比較高的,同步禁用策略的效率和RDB一樣高效。
7.1.2.3 配置AOF
7.1.2.3.1 配置信息
dir /var/redis:可以指定生成的AOF文件和dump文件的位置
appendonly yes:開啟AOF
appendfsync always/everysec/no:AOF策略
l always #每次有數據修改發生時都會寫入AOF文件
l everysec #每秒鍾同步一次,該策略為AOF的缺省策略
l no #從不同步。高效但是數據不會被持久化
重寫AOF:若不滿足重寫條件時,可以手動重寫,命令:bgrewriteaof
7.1.2.3.2 數據恢復演示
1、 flushall操作 清空數據庫
2、 及時關閉redis服務器(防止dump.rdb)。 shutdown nosave
3、 編輯aof文件,將日志中的flushall命令刪除並重啟服務即可
7.2 redis主從復制
7.2.1 步驟
1、 復制一份redis.conf文件並修改名稱,如:cp redis.conf redis6380.conf
2、 修改redis6380.conf文件中的
l 端口號
l 進程id號(pidfile /var/run/redis6380.pid)
l slaveof:主從復制信息
l 存放aof、rdb文件的目錄。
3、 啟動從服務器:bin/redis-cli –p 6380
7.2.2 測試
完成主從數據復制。
8 redis使用場景
1、 取最新N個數據的操作
比如典型的取你網站的最新文章,通過下面方式,我們可以將最新的5000條評論的ID放在Redis的List集合中,並將超出集合部分從數據庫獲取
(1)使用LPUSH latest.comments <ID>命令,向list集合中插入數據
(2)插入完成后再用LTRIM latest.comments 0 5000命令使其永遠只保存最近5000個ID
(3)然后我們在客戶端獲取某一頁評論時可以用下面的邏輯(偽代碼)
# 偽代碼
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甚至可以構建有優先級的隊列系統。