1、Redis和memched有什么區別?為什么單線程的Redis比多線程的Memched效率要高?
區別:
數據支持類型:
Redis:
String(字符串):key-value 類型
Hash(哈希):字典(hashmap) Redis的哈希結構可以使你像在數據庫中更新一個屬性一樣只修改某一項屬性值
List(列表):實現消息隊列
Set(集合):利用唯一性
Sorted Set(有序集合):可以進行排序 可以實現數據持久化
Bitmaps(位圖)
HyperLogLog、Geo(地理信息定位)
Memched:簡單的key/value數據類型
數據持久性:
Redis:Redis通過RDB(Redis DataBase)與AOF(Append Only File)持久化,可以將內存中的數據保存到硬盤中,然后重啟之后在讀取數據。
這里說明一下RDB和AOF的原理:
RDB:是在達到指定的時間或者操作次數后,自動將在內存中的數據寫入磁盤(數據恢復時一致性和完整性較差,因為也許最后一次備份前就宕機了,適合數據量較大的數據恢復時候使用)
AOF:是日志形式,當數據寫入內存中的時候,在日志文件下記錄下所有寫操作。(數據量較大時,數據的恢復緩慢)
注意:如果不需要持久化的功能,可以關閉。如果想要達到持久化的效果,建議兩者都使用(RDB,AOF)
Memched:不支持數據的持久性的存儲
內存利用情況:
使用簡單的key-value存儲的話,Memcached的內存利用率更高。
而如果Redis采用hash結構來做key-value存儲,由於其組合式的壓縮(用哈希編碼得到key值 查找再用產生哈希編碼的算法,算回去,即可得到value,不用遍歷),其內存利用率會高於Memcached。
Memcached默認使用Slab Allocation機制管理內存,主要思想是按照原先預定的大小分配內存大小,當客戶端發過來數據的時候會選擇一個最適合的地方給它儲存,好處是效率高,
不會造成內存碎片,但是不好的一點就是分配的內存大小124字節,傳進來的大小是100字節,那么24字節的內存也就浪費了。
事務:
Redis提供事務
menched不提供
線程:
Redis 單線程
menched多線程
性能區別:
Redis使用單核,
Memcached可以使用多核
在處理小的文件的時候Redis會比Memcached有更高的效率,但是在100KB以上的時候,Memcached的效率就會比Redis更高一點
2、Redis有什么數據類型?都在哪些場景下使用?
String(字符串):key-value 類型
Hash(哈希):字典(hashmap) Redis的哈希結構可以使你像在數據庫中更新一個屬性一樣只修改某一項屬性值
List(列表):實現消息隊列
Set(集合):利用唯一性,判斷集合中是否有已存在的成員
Sorted Set(有序集合):可以進行排序
Bitmaps(位圖)
HyperLogLog、Geo(地理信息定位)
3、Redis的主從復制是怎么實現的?Redis的集群模式是如何實現的?Redis的key是如何尋址的?
主從復制:
a.從服務器連接主服務器,發送SYNC命令(寫緩存命令);
b.主服務器接收到SYNC命名后,開始執行BGSAVE命令生成RDB文件並使用緩沖區記錄此后執行的所有寫命令;
Bgsave 命令用於在后台異步保存當前數據庫的數據到磁盤。
c.主服務器BGSAVE執行完后,向所有從服務器發送快照文件,並在發送期間繼續記錄被執行的寫命令;
d.從服務器收到快照文件后丟棄所有舊數據,載入收到的快照;
e.主服務器快照發送完畢后開始向從服務器發送緩沖區中的寫命令;
f.從服務器完成對快照的載入,開始接收命令請求,並執行來自主服務器緩沖區的寫命令;
集群模式:Redis集群中內置了 16384 個哈希槽,當需要在 Redis 集群中放置一個 key-value 時,redis 先對key 使用
crc16 算法算出一個結果,然后把結果對 16384 求余數,這樣每個 key 都會對應一個編號在 0-16383 之間的哈希槽,redis
會根據節點數量大致均等的將哈希槽映射到不同的節點
Redis的key是如何尋址的?
redis采取鏈表的方式來存儲多個哈希碰撞的鍵。也就是說,當根據key的哈希值找到該列表后,如果列表的長度大於1,那么我們需要遍歷該鏈表來找到我們所查找的key。當然,一般情況下鏈表長度都為是1,所以時間復雜度可看作o(1)。我們知道如果哈希表數據量達到了一個很大的量級,那么沖突的鏈的元素數量就會很大,這時查詢效率就會變慢,因為取值的時候redis會遍歷鏈表。而隨着數據量的縮減,也會產生一定的內存浪費。redis在設計時充分考慮了字典的增加和縮減,為了優化數據量增加時的查詢效率和縮減時的內存利用率,redis進行了一系列操作,而處理的這個過程被稱作rehash。
a、當拿到一個key后, redis 先判斷當前庫的0號哈希表是否為空,
即:if (dict->ht[0].size == 0)。如果為true直接返回NULL。
b、判斷該0號哈希表是否需要rehash,因為如果在進行rehash,那么兩個表中者有可能存儲該key。如果正在進行rehash,將調用一次_dictRehashStep方法,_dictRehashStep 用於對數據庫字典、以及哈希鍵的字典進行被動 rehash,這里不作贅述。
c、計算哈希表,根據當前字典與key進行哈希值的計算。
d、根據哈希值與當前字典計算哈希表的索引值。
e、根據索引值在哈希表中取出鏈表,遍歷該鏈表找到key的位置。一般情況,該鏈表長度為1。
f、當 ht[0] 查找完了之后,再進行了次rehash判斷,如果未在rehashing,則直接結束,否則對ht[1]重復345步驟。
4、使用Redis如何設計分布式鎖?使用zk可以嗎?如何實現?這兩個哪個效率更高?
分布式鎖:
a.在redis里創建一個key算加鎖
輸入命令:SET my:lock 隨機值 NX PX 30000
NX:只有key不存在的時候才會設置成功,
PX 30000:30秒后鎖自動釋放
特點:別人創建的時候如果發現已經有了就不能加鎖了。
釋放鎖:刪除key
b. RedLock算法
例如有一個redis cluster,有5個redis master實例。
然后執行如下步驟獲取一把鎖:
1)獲取當前時間戳,單位是毫秒
2)跟a類似,輪流嘗試在每個master節點上創建鎖,過期時間較短,一般就幾十毫秒
3)嘗試在大多數節點上建立一個鎖,比如5個節點就要求是3個節點(n / 2 +1)
4)客戶端計算建立好鎖的時間,如果建立鎖的時間小於超時時間,就算建立成功了
5)要是鎖建立失敗了,那么就依次刪除這個鎖
6)只要別人建立了一把分布式鎖,你就得不斷輪詢去嘗試獲取鎖
zk分布式鎖
某個節點嘗試創建臨時znode,此時創建成功了就獲取了這個鎖;這個時候別的客戶端來創建鎖會失敗,只能注冊個監聽器監聽這個鎖。釋放鎖就是刪除這個znode,一旦釋放掉就會通知客戶端,然后有一個等待着的客戶端就可以再次重新枷鎖。
效率比較:
redis分布式鎖,其實需要自己不斷去嘗試獲取鎖,比較消耗性能
zk(zookeeper)分布式鎖,獲取不到鎖注冊個監聽器即可,不需要不斷主動嘗試獲取鎖,性能開銷較小
zk分布式鎖會自動嘗試獲取鎖自然是比自己去獲取鎖效率更高
5、知道Redis的持久化嗎?都有什么缺點和優點?具體底層實現呢?
持久化有兩種方案:RDB和AOF
RDB:
優點:最大化發揮redis的性能,主進程不需要進行任何I/O操作,只需要派生一個子進程來處理,文件非常緊湊,恢復數據的效率高。
缺點:數據恢復時一致性和完整性較差,因為也許最后一次備份前就宕機了,那么在最后一次備份到宕機中間的數據是不會存在的
AOF:
優點:能保持數據的一致性和完整性
缺點:AOF文件比RDB文件大,在讀取過程中,會比RDB更慢一些。
底層實現
RDB:是在達到指定的時間或者操作次數后,自動將在內存中的數據寫入磁盤
AOF:是日志形式,當數據寫入內存中的時候,在日志文件下記錄下所有寫操作。
6、Redis過期策略都有哪些?
定期刪除:指的是redis默認是每隔100ms就隨機抽取一些設置了過期時間的key,檢查其是否過期,如果過期就刪除。
惰性刪除:在你獲取某個key的時候,redis會檢查一下 ,這個key如果設置了過期時間那么是否過期了,如果過期了此時就會刪除,不會給你返回任何東西。
內存淘汰:
1)noeviction:當內存不足以容納新寫入數據時,新寫入操作會報錯
2)allkeys-lru:當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的key
3)allkeys-random:當內存不足以容納新寫入數據時,在鍵空間中,隨機移除某個key
4)volatile-lru:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,移除最近最少使用的key
5)volatile-random:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,隨機移除某個key
6)volatile-ttl:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,有更早過期時間的key優先移除