1、Redis 在內存使用上是如何開源節流算法
Redis 跟其餘傳統數據庫不一樣,Redis 是一個純內存的數據庫,而且存儲了都是一些數據結構的數據,若是不對內存加以控制的話,Redis 極可能會由於數據量過大致使系統的奔潰。數據庫
一、Ziplist安全
當最開始嘗試開啓一個小數據量的 Hash 結構和一個 Zset 結構時,發現他們在 Redis 裏面的真正結構類型是一個 Ziplist。服務器
Ziplist 是一個緊湊的數據結構,每個元素之間都是連續的內存,若是在 Redis 中,Redis 啓用的數據結構數據量很小時,Redis 就會切換到使用緊湊存儲的形式來進行壓縮存儲。網絡
例如,上面的例子,咱們採用了 Hash 結構進行存儲,Hash 結構是一個二維的結構,是一個典型的用空間換取時間的結構。數據結構
可是若是使用的數據量很小,使用二維結構反而浪費了空間,在時間的性能上也並無獲得太大的提高,還不如直接使用一維結構進行存儲。併發
在查找的時候,雖然複雜度是 O(n),可是由於數據量少遍歷也很是快,增至比 Hash 結構自己的查詢更快。函數
若是當集合對象的元素不斷的增長,或者某個 Value 的值過大,這種小對象存儲也會升級生成標準的結構。性能
Redis 也能夠在配置中進行定義緊湊結構和標準結構的轉換參數:ui
二、Quicklist
Quicklist 數據結構是 Redis 在 3.2 才引入的一個雙向鏈表的數據結構,確實來講是一個 Ziplist 的雙向鏈表。
Quicklist 的每個數據節點是一個 Ziplist,Ziplist 自己就是一個緊湊列表。
假使,Quicklist 包含了 5 個 Ziplist 的節點,每一個 Ziplist 列表又包含了 5 個數據,那麼在外部看來,這個 Quicklist 就包含了 25 個數據項。
Quicklist 的結構設計簡單總結起來,是一個空間和時間的折中方案:
其次是因爲每一個節點都是獨立的,在內存地址上並不連續,節點多了容易產生內存碎片。
因此,結合 Ziplist 和雙向鏈表的優勢,Quciklist 就孕育而生。
三、對象共享
Redis 在本身的對象系統中構建了一個引用計數方法,經過這個方法程序能夠跟蹤對象的引用計數信息,除了能夠在適當的時候進行對象釋放,還能夠用來做爲對象共享。
舉個例子,假使鍵 A 建立了一個整數值 100 的字符串做爲值對象,這個時候鍵 B 也建立保存一樣整數值 100 的字符串對象做爲值對象。
那麼在 Redis 的操做時:
假使,咱們的數據庫中指向整數值 100 的鍵不止鍵 A 和鍵 B,而是有幾百個,那麼 Redis 服務器中只須要一個字符串對象的內存就能夠保存本來須要幾百個字符串對象的內存才能保存的數據。
2、Redis 是如何實現主從複製
幾個定義:
在 Redis 2.8 以後,使用 Psync 命令代替 Sync 命令來執行復制的同步操做。
Psync 命令具備完整重同步和部分重同步兩種模式:
完整重同步:
若是網絡的抖動或者是短期的斷鏈也須要進行完整同步就會致使大量的開銷,這些開銷包括了,Bgsave 的時間,RDB 文件傳輸的時間,Slave 從新加載 RDB 時間,若是 Slave 有 AOF,還會致使 AOF 重寫。
這些都是大量的開銷,因此在 Redis 2.8 以後也實現了部分重同步的機制。
部分重同步:
3、Redis 是怎麼制定過時刪除策略的
當一個鍵處於過時的狀態,其實在 Redis 中這個內存並非實時就被從內存中進行摘除,而是 Redis 經過必定的機制去把一些處於過時鍵進行移除,進而達到內存的釋放,那麼當一個鍵處於過時,Redis 會在何時去刪除?
幾時被刪除存在三種可能性,這三種可能性也表明了 Redis 的三種不一樣的刪除策略。
一、定時刪除
設置鍵的過時時間,建立定時器,一旦過時時間來臨,就當即對鍵進行操做。
這種對內存是友好的,可是對 CPU 的時間是最不友好的,特別是在業務繁忙,過時鍵不少的時候,刪除過時鍵這個操做就會佔據很大一部分 CPU 的時間。
要知道 Redis 是單線程操做,在內存不緊張而 CPU 緊張的時候,將 CPU 的時間浪費在與業務無關的刪除過時鍵上面,會對 Redis 的服務器的響應時間和吞吐量形成影響。
另外,建立一個定時器須要用到 Redis 服務器中的時間事件,而當前時間事件的實現方式是無序鏈表,時間複雜度爲 O(n),讓服務器大量建立定時器去實現定時刪除策略,會產生較大的性能影響,因此,定時刪除並非一種好的刪除策略。
二、惰性刪除
與定時刪除相反,惰性刪除策略對 CPU 來講是最友好的,程序只有在取出鍵的時候纔會進行檢查,是一種被動的過程。
與此同時,惰性刪除對內存來講又是最不友好的,一個鍵過時,只要再也不被取出,這個過時鍵就不會被刪除,它佔用的內存也不會被釋放。
很明顯,惰性刪除也不是一個很好的策略,Redis 是很是依賴內存和較好內存的,若是一些長期鍵長期沒有被訪問,就會形成大量的內存垃圾,甚至會操成內存的泄漏。
在對執行數據寫入時,經過 expireIfNeeded 函數對寫入的 Key 進行過時判斷。
其中 expireIfNeeded 在內部作了三件事情,分別是:
三、按期刪除
上面兩種刪除策略,不管是定時刪除和惰性刪除,這兩種刪除方式在單一的使用上都存在明顯的缺陷,要麼佔用太多 CPU 時間,要麼浪費太多內存。
按期刪除策略是前兩種策略的一個整合和折中:
note: 一我的真正的安全感,來自於心裏的自信。