Redis與Memcached區(qū)別:
兩者都是非關(guān)系型數(shù)據(jù)庫。主要有以下不同:
數(shù)據(jù)類型:
- Memcached僅支持字符串類型。
- redis支持:String,List,set,zset,hash 可以靈活的解決問題。
數(shù)據(jù)持久化:
- Memcached不支持持久化。
- Redis采用兩種持久化策略:RDB快照和AOF日志。
分布式:
- Mencached不支持分布式,只能在客戶端使用一致性hash來實現(xiàn)分布式存儲,這種方式在存儲和查詢時都需要在客戶端先計算一次數(shù)據(jù)所在的節(jié)點。
- redis cluster實現(xiàn)了分布式的支持。
內(nèi)存管理機制:
- redis中,并不是所有數(shù)據(jù)都一直存儲在內(nèi)存中,可以將一些很久沒用的value交換到磁盤,而memcached數(shù)據(jù)則候會一直在內(nèi)存中。
- memcached將內(nèi)存分割成特定的塊進(jìn)行存儲,以完全解決內(nèi)存碎片化的問題,但是這種方式使得內(nèi)存利用率不高,如塊大小128bytes,只存儲了100bytes的數(shù)據(jù),那么剩下的28bytes就浪費掉了。
鍵的過期時間:
redis可以為每個鍵設(shè)置過期時間,當(dāng)鍵過期時,自動刪除該鍵。
對于散列表這種容器,只能為整個鍵設(shè)置過期時間(整個散列表),而不是為鍵里面的單個元素設(shè)置過期時間。
設(shè)置鍵的生存時間:
- expire: 指定秒
- pexpire: 指定毫秒
127.0.0.1:6379> set key hello
OK
127.0.0.1:6379> expire key 1
(integer) 1
127.0.0.1:6379> get key
(nil)
127.0.0.1:6379> hset hashkey key1 1
(integer) 0
127.0.0.1:6379> hget hashkey key1
"1"
127.0.0.1:6379> expire hashkey 1
(integer) 1
127.0.0.1:6379> hget hashkey key1
(nil)
127.0.0.1:6379> zadd zset 0 key1 1 key2
(integer) 0
127.0.0.1:6379> zrange zset 0 -1
1) "key1"
2) "key3"
3) "key2"
127.0.0.1:6379> expire zset 1
(integer) 1
127.0.0.1:6379> zrange zset 0 -1
(empty list or set)
設(shè)置過期時間:過期時間是一個unix時間戳
- expireat:秒精度
- pexpireat:毫秒精度
過期鍵的刪除策略:
定時刪除:
在設(shè)置鍵的過期時間的同時,創(chuàng)建一個定時器,讓定時器在鍵過期時間來臨時,立即執(zhí)行對鍵的刪除操作。
- [ ] 優(yōu)點:對內(nèi)存是友好的,可以保證過期鍵會盡可能快被刪除,并釋放過期鍵所占用的內(nèi)存。
- [ ] 缺點:對CPU不友好,在過期鍵較多的情況下,刪除鍵的操作會占用相當(dāng)一部分的CPU時間,在內(nèi)存不緊張但CPU緊張的情況下,將cpu時間用在刪除與當(dāng)前任務(wù)無關(guān)的過期鍵上,無疑會對服務(wù)器的響應(yīng)時間和吞吐量造成影響。
此外,定時器需要使用redis服務(wù)器的時間事件,時間事件的實現(xiàn)方式為無序鏈表,查找一個事件的事件復(fù)雜度為O(N),因此創(chuàng)建大量的定時器不現(xiàn)實。
惰性刪除:
僅在程序取出鍵時才進(jìn)行過期檢查
- [ ] 優(yōu)點: CPU友好,不會花費額外的時間。
- [ ] 缺點:對內(nèi)存不友好,會造成內(nèi)存泄漏。
定期刪除:
每隔一段時間執(zhí)行一次刪除過期鍵操作,并通過限制刪除操作執(zhí)行的時長和頻率來減少對CPU時間的影響。
數(shù)據(jù)淘汰策略:6種
可以設(shè)置內(nèi)存最大使用量,當(dāng)內(nèi)存使用超出時,施行數(shù)據(jù)淘汰策略。
作為內(nèi)存數(shù)據(jù)庫,出于對性能和內(nèi)存消耗的考慮,redis的淘汰算法實際上并未針對所有key,而是抽樣一小部分并且從中選出被淘汰的key。
使用reids緩存數(shù)據(jù)時,為提高緩存命中率,需要保證緩存都是熱點數(shù)據(jù)??梢詫?nèi)存最大使用量設(shè)置為熱點數(shù)據(jù)占用的內(nèi)存量,然后啟用allkeys-lru淘汰策略,將最近最少未使用的數(shù)據(jù)進(jìn)行淘汰。
redis4.0 版本后引入了volatile-lfu和allkeys-lfu淘汰策略,LFU策略通過統(tǒng)計訪問頻率,將訪問頻率最小的鍵值進(jìn)行淘汰。
持久化:
redis是內(nèi)存型數(shù)據(jù)庫,為了保證數(shù)據(jù)在斷電后不會丟失,需要將內(nèi)存中的數(shù)據(jù)持久化到硬盤上。
RDB持久化:
- 將某個時間點的所有數(shù)據(jù)都存放到硬盤上。
- 可以將快照復(fù)制到其他服務(wù)器從而創(chuàng)建具有相同數(shù)據(jù)的服務(wù)器副本。
- 如果系統(tǒng)方法故障,將會丟失最后一次快照后的數(shù)據(jù)。
- 如果數(shù)據(jù)量很大,保存快照時間會很長。
手動觸發(fā):
- [ ] redis命令
- save:生成RDB文件,會阻塞服務(wù)器進(jìn)程,知直到RDB文件創(chuàng)建完畢。
- bgsave: 派生(fork)一個子進(jìn)程,然后由子進(jìn)程負(fù)責(zé)創(chuàng)建RDB文件,父進(jìn)程繼續(xù)處理命令請求。
自動觸發(fā):
- 使用save相關(guān)配置,如“save m n”。表示m秒中對數(shù)據(jù)集進(jìn)行n次修改,就觸發(fā)bgsave。
- 如果從節(jié)點執(zhí)行全量復(fù)制操作,主節(jié)點自動執(zhí)行bgsave生成RDB文件發(fā)送給從文件。
- 執(zhí)行debug reload 命令重新加載redis時,自動觸發(fā)save操作。
- 默認(rèn)情況下執(zhí)行shutdown命令時,若沒有開啟AOF持久化功能則自動執(zhí)行bgsave。
優(yōu)缺點:
- [ ] 優(yōu)點: 適用于備份,全量復(fù)制等場景?;謴?fù)數(shù)據(jù)遠(yuǎn)快于AOF方法。
- [ ] 缺點:沒辦法做到實時持久化/秒級持久化。 RDB使用特定二進(jìn)制格式,redis演化中有多個RDB版本,存在版本不兼容情況。
AOF 持久化:
將寫命令添加到AOF文件的末尾(append Only File)
使用AOF持久化需要設(shè)置同步選項,從而保證寫命令什么時候會被同步到磁盤文件上。這時因為對文件進(jìn)行寫入并不會,馬上將內(nèi)容同步到磁盤上,而是先存儲到緩沖區(qū),然后由操作系統(tǒng)決定什么時候同步到磁盤。有以下同步方式:
- always:每個寫命令都同步。嚴(yán)重影響服務(wù)器性能
- everysec:每秒同步一次??梢员WC系統(tǒng)崩潰時只丟失一秒左右的數(shù)據(jù),每秒執(zhí)行一次對性能幾乎沒影響。
- no:讓操作系統(tǒng)決定,最長30秒。不能帶來太多的性能提升,但是會增加系統(tǒng)崩潰時數(shù)據(jù)丟失的數(shù)量。
隨著服務(wù)器寫請求的增多,AOF文件會越來越大。redis提供了一種將AOF重寫的特性,能夠去除AOF文件中冗余的寫命令。