1. 程式人生 > 實用技巧 >Naocs 配置中心報錯問題

Naocs 配置中心報錯問題

目錄

Redis基礎

Redis 是 C 語言開發的一個開源的(遵從 BSD 協議)高效能鍵值對(key-value)的記憶體資料庫,可以用作資料庫、快取、訊息中介軟體等。它是一種 NoSQL(not-only sql,泛指非關係型資料庫)的資料庫。

優點:

  • 效能優秀,資料存在記憶體中,讀寫速度非常快,支援併發10W QPS。
  • 單程序單執行緒,是執行緒安全的,採用 IO 多路複用機制。
  • 豐富的資料型別,支援字串(string)、雜湊雜湊(hash)、列表(list)、集合(set)以及有序集合(sorted set)。
  • 支援資料持久化。可以將記憶體資料儲存到磁碟中,重啟時載入。
  • 支援高可用。持主從複製、哨兵。

基本使用場景:

  • 資料儲存
  • 快取
  • 分散式鎖
  • 訊息佇列,支援釋出訂閱

資料型別&結構

redisObject

redisObject 是 Redis 型別系統的核心, 資料庫中的每個鍵、值,以及 Redis 本身處理的引數, 都表示為這種資料型別。

redis是c語言開發的,redisObject 資料結構如下:

/*
 * Redis 物件
 */
typedef struct redisObject {
    unsigned type:4;		// 型別
    unsigned notused:2;		// 對齊位
    unsigned encoding:4;	// 編碼方式
    unsigned lru:22;		// LRU 時間(相對於 server.lruclock)
    int refcount;			// 引用計數
    void *ptr;				// 指向物件的值
} robj;

型別(type)

  • REDIS_STRING
    :字串
  • REDIS_LIST:列表
  • REDIS_SET:集合
  • REDIS_ZSET:有序集合
  • REDIS_HASH:雜湊表

編碼方式(encoding)

  • REDIS_ENCODING_RAW :SDS 實現的動態字串
  • REDIS_ENCODING_INT:long整型
  • REDIS_ENCODING_HT:雜湊表
  • REDIS_ENCODING_ZIPMAP:壓縮map,(3.0)版本未使用
  • REDIS_ENCODING_LINKEDLIST:雙端連結串列
  • REDIS_ENCODING_ZIPLIST:壓縮列表
  • REDIS_ENCODING_INTSET:整形集合
  • REDIS_ENCODING_SKIPLIST:跳躍表
  • REDIS_ENCODING_EMBSTR:使用 embstr 實現的動態字串

下圖展示了 redisObject 、Redis 所有資料型別、以及 Redis 所有編碼方式(底層實現)三者之間的關係:

image-20200309000001910

image-20200309000157303

字串(String)

string 型別是 Redis 最基本的資料型別,鍵值(key-value)資料結構,string 型別的值最大能儲存 512MB。
string 型別是二進位制安全的。意思是 redis 的 string 可以包含任何資料。比如jpg圖片或者序列化的物件。

編碼方式:
字串物件支援的編碼有:int、raw以及embstr

常用命令:
有:get、set、del、mget、mset、incr、decr...

雜湊雜湊(Hash)

Hash是一個鍵值(key-value)集合,是一個key和values的對映表。

常用命令:hget、hset、hgetall、hdel...

列表(List)

列表是簡單的字串列表,按照插入順序排序。可以新增一個元素到列表的頭部(左邊)或者尾部(右邊)。

常用命令:lpush、rpush、lpop、rpop、lrange(獲取列表片段)等。

應用場景:

  • 訊息佇列。Redis的連結串列結構,可以輕鬆實現阻塞佇列,Redis 提供了 List 的 Push 和 Pop 操作,還可以直接查詢或者刪除某一段的元素。
  • 資料分頁查詢:文章列表或者資料分頁展示的應用。

集合(Set)

Set是Sting型別的無序集合。集合是通過hashtable實現的。set中的元素是無序的,而且不可重複。

常用命令:sdd、spop、smembers、sunion...

應用場景:

  • 資料去重:Set 是無序、元素不重複的集合,可以用作分散式資料去重。
  • 集合操作:Set 支援交集、並集、差集的操作,可以對一些資料進行操作。比如交集,可以把兩個人的好友列表整一個交集,看看倆人的共同好友是誰。

有序集合(Sorted set)

Zset和Set一樣是String型別元素的集合,且不允許重複的元素。

常用命令:zadd、zrange、zrem、zcard等。

使用場景:Sorted Set 可以通過使用者額外提供一個優先順序(score)的引數來為成員排序,並且是插入有序的,即自動排序。當你需要一個有序的並且不重複的集合列表,那麼可以選擇 Sorted Set 結構。

  • 排行榜:有序集合經典使用場景。例如視訊網站需要對使用者上傳的視訊做排行榜,榜單維護可能是多方面:按照時間、按照播放量、按照獲得的贊數等。
  • Sorted Sets來做帶權重的佇列,比如普通訊息的score為1,重要訊息的score為2,然後工作執行緒可以選擇按score的倒序來獲取工作任務。讓重要的任務優先執行。

快取問題

Redis 為何這麼快?

  • redis基於記憶體,絕大多數的請求都是記憶體操作,速度很快。
  • 資料結構簡單,對資料操作也簡單。類似於 HashMap,HashMap 的優勢就是查詢和操作的時間複雜度是 O(1)。
  • 採用單執行緒,避免了不必要的上下文切換和競爭條件。不存在多執行緒導致cpu切換,不用考慮各種鎖的問題,不存在加鎖釋放鎖操作,沒有死鎖問題導致的效能消耗。
  • 使用多路複用 IO 模型,非阻塞 IO。

Redis 和 Memcached 的區別?

  • 儲存方式上:redis支援持久化,而memcache值儲存在記憶體中,斷電後memcache會丟失所有資料。
  • 資料型別上:memcache僅支援簡單的鍵值key-value,而redis支援5中資料型別。
  • 底層模型上:它們之間底層實現方式以及與客戶端之間通訊的應用協議不一樣。Redis 直接自己構建了 VM 機制,因為一般的系統呼叫系統函式的話,會浪費一定的時間去移動和請求。
  • 值的大小上:Redis 可以達到 1GB,而 Memcache 只有 1MB。

淘汰策略有哪些?

redis有8種淘汰策略:

策略 描述
volatile-lru 從已設定過期時間的KV集中優先對最近最少使用(less recently used)的資料淘汰
volatile-ttl 從已經設定過期時間的KV集中優先對剩餘時間短(time to live)的資料淘汰
volatile-random 從已設定過期時間的KV集中隨機選擇資料淘汰
volatile-lfu 統計訪問頻率,從已經設定過期時間的KV集中優先淘汰訪問頻率最低的資料
allKeys-lru 從所有KV集中對最近最少使用(less recently used)的資料淘汰
allKeys-random 從所有KV集中隨機淘汰資料
allkeys-lfu 統計訪問頻率,從所有KV集中淘汰訪問頻率最低的資料
noeviction 不淘汰策略,若超過最大記憶體,返回錯誤資訊

Redis 4.0 加入了 LFU(least frequency use)淘汰策略,包括 volatile-lfu 和 allkeys-lfu,通過統計訪問頻率,將訪問頻率最少,即最不經常使用的 KV 淘汰。

Redis持久化

redis雖然是一種記憶體型資料庫,但也提供持久化方案,將記憶體中的資料儲存到磁碟中,避免資料丟失。

redis支援兩種持久化方案:

  • RDB:持久化可以在指定的時間間隔內生成資料集的時間點快照(point-in-time snapshot)。
  • AOF:記錄每次對redis伺服器寫的操作,當伺服器重啟時會重新執行這些命令來恢復原始資料。

RDB

在預設情況下, Redis 將資料庫快照儲存在名字為 dump.rdb 的二進位制檔案中。

命令

RDB檔案可以通過兩個命令建立:

  • SAVE: 執行一個同步儲存操作(會阻塞redis的服務程序),將當前 Redis 例項的所有資料快照(snapshot)以 RDB 檔案的形式儲存到硬碟。
  • BGSAVE:主程序fork一個子程序來建立新的RDB檔案,記錄接收到的BGSAVE時刻的資料庫狀態,父程序繼續處理接收到的命令。當子程序完成寫臨時檔案後,用新 RDB 檔案替換原來的 RDB 檔案,並刪除舊的 RDB 檔案。

一般來說,在生產環境很少執行 操作,因為它會阻塞所有客戶端,儲存資料庫的任務通常由 命令非同步地執行。然而,如果負責儲存資料的後臺子程序不幸出現問題時, 可以作為儲存資料的最後手段來使用。

優點

  • RDB 檔案是經過壓縮的二進位制檔案,佔用的空間會小於記憶體中的資料,更加利於傳輸,非常適合用於進行備份。
  • RDB 在恢復大資料集時的速度比 AOF 的恢復速度要快。

缺點

  • 使用 RDB 方式實現持久化,一旦 Redis 異常退出,就會丟失最後一次快照以後更改的所有資料。這個時候我們就需要根據具體的應用場景,通過組合設定自動快照條件的方式來將可能發生的資料損失控制在能夠接受範圍。

AOF

快照功能並不是非常耐久(durable): 如果 Redis 因為某些原因而造成故障停機, 那麼伺服器將丟失最近寫入、且仍未儲存到快照中的那些資料。從 1.1 版本開始, Redis 增加了一種完全耐久的持久化方式: AOF(append-only file) 持久化。

具體來說,RDB持久化相當於備份資料庫狀態,而AOF持久化是備份資料庫接收到的命令,所有被寫入AOF的命令都是以redis的協議格式來儲存的。

AOF檔案重寫機制

AOF(append-only file)的運作方式是不斷地將命令追加到檔案的末尾, 所以隨著寫入命令的不斷增加, AOF 檔案的體積也會變得越來越大。但AOF 檔案體積變得過大時,Redis自動地在後臺對 AOF 進行重寫: 重寫後的新 AOF 檔案包含了恢復當前資料集所需的最小命令集合。 整個重寫操作是絕對安全的,因為 Redis 在建立新 AOF 檔案的過程中,會繼續將命令追加到現有的 AOF 檔案裡面,即使重寫過程中發生停機,現有的 AOF 檔案也不會丟失。 而一旦新 AOF 檔案建立完畢,Redis 就會從舊 AOF 檔案切換到新 AOF 檔案,並開始對新 AOF 檔案進行追加操作。

優點

  • 使用 AOF 的優點是會讓 Redis 變得非常耐久。可以設定不同的 fsync 策略,AOF的預設策略是每秒鐘 fsync 一次,在這種配置下,就算髮生故障停機,也最多丟失一秒鐘的資料。
  • AOF 檔案有序地儲存了對資料庫執行的所有寫入操作, 這些寫入操作以 Redis 協議的格式儲存, 因此 AOF 檔案的內容非常容易被人讀懂, 對檔案進行分析(parse)也很輕鬆。

缺點

  • AOF 檔案的體積通常要大於 RDB 檔案的體積。
  • 根據所使用的 fsync 策略,AOF 的速度可能會慢於 RDB 。 在一般情況下, 每秒 fsync 的效能依然非常高, 而關閉 fsync 可以讓 AOF 的速度和 RDB 一樣快, 即使在高負荷之下也是如此。

Redis主從複製

Redis哨兵模式

參考資料