1、Redis的特點?
Redis是由意大利人Salvatore Sanfilippo(網(wǎng)名:antirez)開發(fā)的一款內(nèi)存高速緩存數(shù)據(jù)庫。Redis全稱為:Remote Dictionary Server(遠(yuǎn)程數(shù)據(jù)服務(wù)),該軟件使用C語言編寫,典型的NoSQL數(shù)據(jù)庫服務(wù)器。Redis是一個key-value存儲系統(tǒng),它支持豐富的數(shù)據(jù)類型,如:string、list、set、zset(sorted set)、hash。
Redis本質(zhì)上是一個Key-Value類型的內(nèi)存數(shù)據(jù)庫,很像memcached,整個數(shù)據(jù)庫統(tǒng)統(tǒng)加載在內(nèi)存當(dāng)中進(jìn)行操作,定期通過異步操作把數(shù)據(jù)庫數(shù)據(jù)flush到硬盤上進(jìn)行保存。因為是純內(nèi)存操作,Redis的性能非常出色,每秒可以處理超過10萬次讀寫操作,是已知性能最快的Key-Value DB。
Redis的出色之處不僅僅是性能,Redis最大的魅力是支持保存多種數(shù)據(jù)結(jié)構(gòu),此外單個value的最大限制是1GB,不像memcached只能保存1MB的數(shù)據(jù),另外Redis也可以對存入的Key-Value設(shè)置expire時間。
Redis的主要缺點是數(shù)據(jù)庫容量受到物理內(nèi)存的限制,不能用作海量數(shù)據(jù)的高性能讀寫,因此Redis適合的場景主要局限在較小數(shù)據(jù)量的高性能操作和運算上。
Redis為了達(dá)到最快的讀寫速度將數(shù)據(jù)都讀到內(nèi)存中,并通過異步的方式將數(shù)據(jù)寫入磁盤。所以redis具有快速和數(shù)據(jù)持久化的特征。如果不將數(shù)據(jù)放在內(nèi)存中,磁盤I/O速度為嚴(yán)重影響redis的性能。在內(nèi)存越來越便宜的今天,redis將會越來越受歡迎。如果設(shè)置了最大使用的內(nèi)存,則數(shù)據(jù)已有記錄數(shù)達(dá)到內(nèi)存限值后不能繼續(xù)插入新值。
● Master寫內(nèi)存快照,save命令調(diào)度rdbSave函數(shù),會阻塞主線程的工作,當(dāng)快照比較大時對性能影響是非常大的,會間斷性暫停服務(wù),所以Master最好不要寫內(nèi)存快照。
● Master AOF持久化,如果不重寫AOF文件,這個持久化方式對性能的影響是最小的,但是AOF文件會不斷增大,AOF文件過大會影響Master重啟的恢復(fù)速度。Master最好不要做任何持久化工作,包括內(nèi)存快照和AOF日志文件,特別是不要啟用內(nèi)存快照做持久化,如果數(shù)據(jù)比較關(guān)鍵,某個Slave開啟AOF備份數(shù)據(jù),策略為每秒同步一次。
● Master調(diào)用BGREWRITEAOF重寫AOF文件,AOF在重寫的時候會占大量的CPU和內(nèi)存資源,導(dǎo)致服務(wù)load過高,出現(xiàn)短暫服務(wù)暫?,F(xiàn)象。
● Redis主從復(fù)制的性能問題,為了主從復(fù)制的速度和連接的穩(wěn)定性,Slave和Master最好在同一個局域網(wǎng)內(nèi)。
● 會話緩存(Session Cache)
● 全頁緩存(FPC)
● 隊列
● 排行榜/計數(shù)器
● 發(fā)布/訂閱
● 存儲方式不同,Memcache是把數(shù)據(jù)全部存在內(nèi)存中,數(shù)據(jù)不能超過內(nèi)存的大小,斷電后數(shù)據(jù)庫會掛掉。Redis有部分存在硬盤上,這樣能保證數(shù)據(jù)的持久性。
● 數(shù)據(jù)支持的類型不同memcahe對數(shù)據(jù)類型支持相對簡單,redis有復(fù)雜的數(shù)據(jù)類型。
● 使用底層模型不同 它們之間底層實現(xiàn)方式以及與客戶端之間通信的應(yīng)用協(xié)議不一樣。Redis直接自己構(gòu)建了VM機制,因為一般的系統(tǒng)調(diào)用系統(tǒng)函數(shù)的話,會浪費一定的時間去移動和請求。
● 支持的value大小不一樣redis最大可以達(dá)到1GB,而memcache只有1MB。
● String——字符串
String數(shù)據(jù)結(jié)構(gòu)是簡單的key-value類型,value不僅可以是String,也可以是數(shù)字(當(dāng)數(shù)字類型用Long可以表示的時候encoding就是整型,其他都存儲在sdshdr當(dāng)做字符串)。
● Hash——字典
在Memcached中,我們經(jīng)常將一些結(jié)構(gòu)化的信息打包成hashmap,在客戶端序列化后存儲為一個字符串的值(一般是JSON格式),比如用戶的昵稱、年齡、性別、積分等。
● List——列表
List說白了就是鏈表(redis使用雙端鏈表實現(xiàn)的List)
● Set——集合
Set就是一個集合,集合的概念就是一堆不重復(fù)值的組合。利用Redis提供的Set數(shù)據(jù)結(jié)構(gòu),可以存儲一些集合性的數(shù)據(jù)。
● Sorted Set——有序集合
和Set相比,Sorted Set是將Set中的元素增加了一個權(quán)重參數(shù)score,使得集合中的元素能夠按score進(jìn)行有序排列,
● 帶有權(quán)重的元素,比如一個游戲的用戶得分排行榜
● 比較復(fù)雜的數(shù)據(jù)結(jié)構(gòu),一般用到的場景不算太多
● 優(yōu)點:
性能極高–Redis能支持超過100K+每秒的讀寫頻率。
豐富的數(shù)據(jù)類型–Redis支持二進(jìn)制案例的Strings,Lists,Hashes,Sets及Ordered Sets數(shù)據(jù)類型操作。
原子–Redis的所有操作都是原子性的,同時Redis還支持對幾個操作全并后的原子性執(zhí)行。attention原子性定義:例如,A想要從自己的帳戶中轉(zhuǎn)1000塊錢到B的帳戶里。那個從A開始轉(zhuǎn)帳,到轉(zhuǎn)帳結(jié)束的這一個過程,稱之為一個事務(wù)。如果在A的帳戶已經(jīng)減去了1000塊錢的時候,忽然發(fā)生了意外,比如停電什么的,導(dǎo)致轉(zhuǎn)帳事務(wù)意外終止了,而此時B的帳戶里還沒有增加1000塊錢。那么,我們稱這個操作失敗了,要進(jìn)行回滾。回滾就是回到事務(wù)開始之前的狀態(tài),也就是回到A的帳戶還沒減1000塊的狀態(tài),B的帳戶的原來的狀態(tài)。此時A的帳戶仍然有3000塊,B的帳戶仍然有2000塊。我們把這種要么一起成功(A帳戶成功減少1000,同時B帳戶成功增加1000),要么一起失敗(A帳戶回到原來狀態(tài),B帳戶也回到原來狀態(tài))的操作叫原子性操作。如果把一個事務(wù)可看作是一個程序,它要么完整的被執(zhí)行,要么完全不執(zhí)行,這種特性就叫原子性。
豐富的特性–Redis還支持publish/subscribe,通知key過期等等特性。
● 缺點:
由于是內(nèi)存數(shù)據(jù)庫,所以單臺機器存儲的數(shù)據(jù)量跟機器本身的內(nèi)存大小不一樣。雖然redis本身有key過期策略,但是還是需要提前預(yù)估和節(jié)約內(nèi)存。如果內(nèi)存增長過快,需要定期刪除數(shù)據(jù)。
如果進(jìn)行完整重同步,由于需要生成rdb文件,并進(jìn)行傳輸,會占用主機的CPU,并會消耗現(xiàn)網(wǎng)的帶寬。不過redis2.8版本,已經(jīng)有部分重同步的功能,但是還是有可能有完整重同步的。比如:新上線的備機。
修改配置文件,進(jìn)行重啟,將硬盤中的數(shù)據(jù)加載進(jìn)內(nèi)存,時間比較久。在這個過程中,redis不能提供服務(wù)。
RDB持久化:該機制可以在指定的時間間隔內(nèi)生成數(shù)據(jù)集的時間點快照(point-in-time snapshot)。
AOF持久化:記錄服務(wù)器執(zhí)行的所有寫操作命令,并在服務(wù)器啟動時,通過重新執(zhí)行這些命令來還原數(shù)據(jù)集。AOF文件中的命令全部以Redis協(xié)議的格式來保存,新命令會被追加到文件的末尾。Redis還可以在后臺對AOF文件進(jìn)行重寫(rewrite),使得AOF文件的體積不會超出保存數(shù)據(jù)集狀態(tài)所需的實際大小。
AOF和RDB的同時應(yīng)用:當(dāng)Redis重啟時,它會優(yōu)先使用AOF文件來還原數(shù)據(jù)集,因為AOF文件保存的數(shù)據(jù)集通常比RDB文件所保存的數(shù)據(jù)集更完整。
優(yōu)點:RDB是一個非常緊湊(compact)的文件,它保存了Redis在某個時間點上的數(shù)據(jù)集。這種文件非常適合用于進(jìn)行備份:比如說,你可以在最近的24小時內(nèi),每小時備份一次RDB文件,并且在每個月的每一天,也備份一個RDB文件。這樣的話,即使遇上問題,也可以隨時將數(shù)據(jù)集還原到不同的版本。RDB非常適用于災(zāi)難恢復(fù)(disaster recovery):它只有一個文件,并且內(nèi)容都非常緊湊,可以(在加密后)將它傳送到別的數(shù)據(jù)中心,或者亞馬遜S3中。RDB可以最大化Redis的性能:父進(jìn)程在保存RDB文件時唯一要做的就是fork出一個子進(jìn)程,然后這個子進(jìn)程就會處理接下來的所有保存工作,父進(jìn)程無須執(zhí)行任何磁盤I/O操作。RDB在恢復(fù)大數(shù)據(jù)集時的速度比AOF的恢復(fù)速度要快。
缺點:如果你需要盡量避免在服務(wù)器故障時丟失數(shù)據(jù),那么RDB不適合你。雖然Redis允許你設(shè)置不同的保存點(save point)來控制保存RDB文件的頻率,但是,因為RDB文件需要保存整個數(shù)據(jù)集的狀態(tài),所以它并不是一個輕松的操作。因此你可能會至少5分鐘才保存一次RDB文件。在這種情況下,一旦發(fā)生故障停機,你就可能會丟失好幾分鐘的數(shù)據(jù)。每次保存RDB的時候,Redis都要fork()出一個子進(jìn)程,并由子進(jìn)程來進(jìn)行實際的持久化工作。在數(shù)據(jù)集比較龐大時,fork()可能會非常耗時,造成服務(wù)器在某某毫秒內(nèi)停止處理客戶端;如果數(shù)據(jù)集非常巨大,并且CPU時間非常緊張的話,那么這種停止時間甚至可能會長達(dá)整整一秒。
● 優(yōu)點:
使用AOF持久化會讓Redis變得非常耐久(much more durable):你可以設(shè)置不同的fsync策略,比如無fsync,每秒鐘一次fsync,或者每次執(zhí)行寫入命令時fsync。AOF的默認(rèn)策略為每秒鐘fsync一次,在這種配置下,Redis仍然可以保持良好的性能,并且就算發(fā)生故障停機,也最多只會丟失一秒鐘的數(shù)據(jù)(fsync會在后臺線程執(zhí)行,所以主線程可以繼續(xù)努力地處理命令請求)。AOF文件是一個只進(jìn)行追加操作的日志文件(append onlylog),因此對AOF文件的寫入不需要進(jìn)行seek,即使日志因為某些原因而包含了未寫入完整的命令(比如寫入時磁盤已滿,寫入中途停機,等等),redis-check-aof工具也可以 輕易地修復(fù)這種問題。
Redis可以在AOF文件體積變得過大時,自動地在后臺對AOF進(jìn)行重寫:重寫后的新AOF文件包含了恢復(fù)當(dāng)前數(shù)據(jù)集所需的最小命令集合。整個重寫操作是絕對安全的,因為Redis在創(chuàng)建新AOF文件的過程中,會繼續(xù)將命令追加到現(xiàn)有的AOF文件里面,即使重寫過程中發(fā)生停機,現(xiàn)有的AOF文件也不會丟失。而一旦新AOF文件創(chuàng)建完畢,Redis就會從舊AOF文件切換到新AOF文件,并開始對新AOF文件進(jìn)行追加操作。
● 缺點:
對于相同的數(shù)據(jù)集來說,AOF文件的體積通常要大于RDB文件的體積。根據(jù)所使用的fsync策略,AOF的速度可能會慢于RDB。在一般情況下,每秒fsync的性能依然非常高,而關(guān)閉fsync可以讓AOF的速度和RDB一樣快,即使在高負(fù)荷之下也是如此。不過在處理巨大的寫入載入時,RDB可以提供更有保證的最大延遲時間(latency)。
AOF在過去曾經(jīng)發(fā)生過這樣的bug:因為個別命令的原因,導(dǎo)致AOF文件在重新載入時,無法將數(shù)據(jù)集恢復(fù)成保存時的原樣。(舉個例子,阻塞命令BRPOPLPUSH就曾經(jīng)引起過這樣的bug。)測試套件里為這種情況添加了測試:它們會自動生成隨機的、復(fù)雜的數(shù)據(jù)集,并通過重新載入這些數(shù)據(jù)來確保一切正常。雖然這種bug在AOF文件中并不常見,但是對比來說,RDB幾乎是不可能出現(xiàn)這種bug的。