redis是一個開源的使用C語言編寫的一個kv存儲系統
發布時間:2019/9/2 14:55:06 訪問次數:2806
關于Redis
redis是一個開源的使用C語言編寫的一個kv存儲系統,是一個速度非常快的非關系遠程內存數據庫。它支持包括String、List、Set、Zset、hash五種數據結構。除此之外,通過復制、持久化和客戶端分片等特性,用戶可以很方便地將redis擴展成一個能夠包含數百GB數據和每秒處理上百萬次的請求的系統。目前支持多種語言的api,方便用戶使用。
redis同時也內置了事務、LUA腳本、復制等功能,提供兩種持久化選項,一種是每隔一段時間將數據導入到磁盤(快照模式),另一種是追加命令到日志中(AOF模式)。如果只是作為高效的內存數據庫使用也可以關閉持久化功能。通過哨兵(sentinel)和自動分區(Cuuster)的方式可以提高redis服務器的高可用性。
與關系型數據庫相比,redis的命令請求不需要經過查詢分析器或查詢優化器進行處理,也避免了更新數據時引起的隨機讀\寫,這些慢操作。它直接讀寫內存中的數據,并且數據是按照一定的數據結構存儲的。所以它的速度非常快。
不同于memcached等完全基于內存的緩存中間件,Redis同時還提供了持久化功能,這也是為什么Redis不僅可以用來做數據緩存還可以用來做數據存儲,服務器節點宕機之后可以通過事先持久化的數據還原數據到某個時間點的狀態。Redis提供了兩種持久化機制RDB和AOF,準確的講應該是三種,Redis還提供了虛擬內存機制,但是性能比較差,使用場景有限。
RDB持久化是把當前數據庫中的數據備份到一個RDB文件中,RDB文件是一個經過壓縮的二進制文件,通過這個文件可以還原生成RDB文件時的數據庫狀態。
Redis提供了兩個命令用于生成RDB文件,即SAVE和BGSAVE。SAVE命令會阻塞主進程,在執行該命令的過程中服務器會拒絕客戶端命令。只有當SAVE命令執行完之后服務器才會繼續處理客戶端的命令,而BGSAVE命令是在子進程中執行,在執行該命令的過程中服務器還可以繼續處理客戶端的命令。SAVE命令和BGSAVE命令不能同時執行,當正在執行BGSAVE命令時,客戶端發送的SAVE命令會被拒絕,兩個BGSAVE命令也不能同時執行。
服務器在900秒之內對數據庫進行了至少一次修改。服務器在300秒之內對數據庫進行了至少10次修改。服務器在60秒之內對數據庫進行了至少10000次修改。Redis通過一個saveparam結構體來保存save參數:
intset優化set
當set集合中的元素為整數且元素個數小于配置set-max-intset-entries值時,使用intset數據結構存儲,否則轉化為Dict結構,Dict實際是Hash Table的一種實現,key為元素值,value為NULL,這樣即可在O(1)時間內判斷集合中是否包含某個元素。
intset中有三種類型數組:int16_t類型、int32_t 類型、 int64_t 類型。至于怎么選擇是那種類型的數組,是根據其保存的值的取值范圍來決定的,初始化時是 int16_t,根據 set 中的***值在[INT16_MIN, INT16_MAX] , [INT32_MIN, INT32_MAX], [INT64_MIN, INT64_MAX]的那個取值范圍來動態確定整個數組的類型。例如set一開始是 int16_t 類型,當一個取值范圍在 [INT32_MIN, INT32_MAX]的值加入到 set 時,則將保存 set 的數組升級成 int32_t 的數組。
服務器結構體redisServer添加了三個字段:saveparams字段,保存所有的save參數。dirty字段,來保存上一次成功執行SAVE或BGSAVE命令之后,服務器對數據庫執行的修改次數。lastsave字段,記錄服務器上一次執行SAVE和BGSAVE的UNIX時間戳。RDB是通過備份某個時間點的數據來保存數據庫狀態,而AOF是通過保存服務器所執行的命令來保存數據庫的狀態的。當結點宕機重啟時通過載入AOF文件并且執行文件中的命令就可以恢復生成AOF文件時的數據庫狀態,如果同時存在RDB文件和AOF文件,服務器優先載入AOF文件來還原數據庫狀態。
AOF實現分為三步:命令追加、文件寫入、文件同步。現代操作系統中為了提高文件寫入效率,當用戶調用了write函數時操作系統通常會將寫入的數據暫時保存在一個內存緩沖區里面,等到緩沖區寫滿或者超過指定的時限之后,才真正地將緩沖區中的數據寫入到磁盤中。
關于redis中數據存儲的機制解析
這種方式CPU消耗低,但是數據安全性差,而且單次同步時間最長。如果用戶不進行設置,默認值為everysec。相比于RDB持久化,AOF持久化執行的頻率要高得多,所以AOF丟失數據的時間窗比RDB要小,但是也要耗費更多的CPU時間和IO資源。RDB和AOF還有一個不同點就是,RDB文件替換是一個原子操作所以RDB文件肯定是完整,而AOF文件有可能是不完整的,有可能命令沒寫完就宕機了或者磁盤壞了。但是也不用擔心這種情況,一是這種情況出現的概率非常低,二是Redis提供了修復AOF文件的工具。
當Redis服務器長時間運行時,AOF文件的內容會越來越多,文件的體積也會越來越大,為了解決這個問題,Redis提供了AOF文件重寫功能,消除一些冗余命令。
Redis提供了 BGREWRITEAOF命令來執行AOF重寫,AOF重寫不對舊AOF文件有依賴,而是通過查詢現有數據庫中的鍵值對的狀態來生成一個新的AOF文件,重寫動作在子進程中完成,生成一個新文件然后重命名替換掉老文件。在重寫的過程中,客戶端請求的新命令會追加到AOF重寫緩沖區中,子進程完成重寫之后,發送一個信號消息通知主進程把重寫緩沖區中的內容同步到重寫后的AOF文件中,這個過程會阻塞主進程。
通過設置appendfsync參數來設置AOF文件生成策略,它有三個可選值:
always,將AOF緩沖區的所有內容寫入并同步到AOF文件中,這種方式數據安全性最高,但是CPU消耗大。everysec,將AOF緩沖區中的所有內容寫入到AOF文件,如果上次同步AOF文件的時候距離現在超過一秒鐘,那么再次對AOF文件進行同步,并且這個同步操作由一個線程專門負責執行,數據安全性不如always,當服務器出現故障時會出現1s的數據空窗期,但是CPU消耗較always小。no,將AOF緩沖區中的所有內容寫入到AOF文件,但并不對AOF文件進行同步,何時同步由操作系統來決定。
關于Redis
redis是一個開源的使用C語言編寫的一個kv存儲系統,是一個速度非常快的非關系遠程內存數據庫。它支持包括String、List、Set、Zset、hash五種數據結構。除此之外,通過復制、持久化和客戶端分片等特性,用戶可以很方便地將redis擴展成一個能夠包含數百GB數據和每秒處理上百萬次的請求的系統。目前支持多種語言的api,方便用戶使用。
redis同時也內置了事務、LUA腳本、復制等功能,提供兩種持久化選項,一種是每隔一段時間將數據導入到磁盤(快照模式),另一種是追加命令到日志中(AOF模式)。如果只是作為高效的內存數據庫使用也可以關閉持久化功能。通過哨兵(sentinel)和自動分區(Cuuster)的方式可以提高redis服務器的高可用性。
與關系型數據庫相比,redis的命令請求不需要經過查詢分析器或查詢優化器進行處理,也避免了更新數據時引起的隨機讀\寫,這些慢操作。它直接讀寫內存中的數據,并且數據是按照一定的數據結構存儲的。所以它的速度非常快。
不同于memcached等完全基于內存的緩存中間件,Redis同時還提供了持久化功能,這也是為什么Redis不僅可以用來做數據緩存還可以用來做數據存儲,服務器節點宕機之后可以通過事先持久化的數據還原數據到某個時間點的狀態。Redis提供了兩種持久化機制RDB和AOF,準確的講應該是三種,Redis還提供了虛擬內存機制,但是性能比較差,使用場景有限。
RDB持久化是把當前數據庫中的數據備份到一個RDB文件中,RDB文件是一個經過壓縮的二進制文件,通過這個文件可以還原生成RDB文件時的數據庫狀態。
Redis提供了兩個命令用于生成RDB文件,即SAVE和BGSAVE。SAVE命令會阻塞主進程,在執行該命令的過程中服務器會拒絕客戶端命令。只有當SAVE命令執行完之后服務器才會繼續處理客戶端的命令,而BGSAVE命令是在子進程中執行,在執行該命令的過程中服務器還可以繼續處理客戶端的命令。SAVE命令和BGSAVE命令不能同時執行,當正在執行BGSAVE命令時,客戶端發送的SAVE命令會被拒絕,兩個BGSAVE命令也不能同時執行。
服務器在900秒之內對數據庫進行了至少一次修改。服務器在300秒之內對數據庫進行了至少10次修改。服務器在60秒之內對數據庫進行了至少10000次修改。Redis通過一個saveparam結構體來保存save參數:
intset優化set
當set集合中的元素為整數且元素個數小于配置set-max-intset-entries值時,使用intset數據結構存儲,否則轉化為Dict結構,Dict實際是Hash Table的一種實現,key為元素值,value為NULL,這樣即可在O(1)時間內判斷集合中是否包含某個元素。
intset中有三種類型數組:int16_t類型、int32_t 類型、 int64_t 類型。至于怎么選擇是那種類型的數組,是根據其保存的值的取值范圍來決定的,初始化時是 int16_t,根據 set 中的***值在[INT16_MIN, INT16_MAX] , [INT32_MIN, INT32_MAX], [INT64_MIN, INT64_MAX]的那個取值范圍來動態確定整個數組的類型。例如set一開始是 int16_t 類型,當一個取值范圍在 [INT32_MIN, INT32_MAX]的值加入到 set 時,則將保存 set 的數組升級成 int32_t 的數組。
服務器結構體redisServer添加了三個字段:saveparams字段,保存所有的save參數。dirty字段,來保存上一次成功執行SAVE或BGSAVE命令之后,服務器對數據庫執行的修改次數。lastsave字段,記錄服務器上一次執行SAVE和BGSAVE的UNIX時間戳。RDB是通過備份某個時間點的數據來保存數據庫狀態,而AOF是通過保存服務器所執行的命令來保存數據庫的狀態的。當結點宕機重啟時通過載入AOF文件并且執行文件中的命令就可以恢復生成AOF文件時的數據庫狀態,如果同時存在RDB文件和AOF文件,服務器優先載入AOF文件來還原數據庫狀態。
AOF實現分為三步:命令追加、文件寫入、文件同步。現代操作系統中為了提高文件寫入效率,當用戶調用了write函數時操作系統通常會將寫入的數據暫時保存在一個內存緩沖區里面,等到緩沖區寫滿或者超過指定的時限之后,才真正地將緩沖區中的數據寫入到磁盤中。
關于redis中數據存儲的機制解析
這種方式CPU消耗低,但是數據安全性差,而且單次同步時間最長。如果用戶不進行設置,默認值為everysec。相比于RDB持久化,AOF持久化執行的頻率要高得多,所以AOF丟失數據的時間窗比RDB要小,但是也要耗費更多的CPU時間和IO資源。RDB和AOF還有一個不同點就是,RDB文件替換是一個原子操作所以RDB文件肯定是完整,而AOF文件有可能是不完整的,有可能命令沒寫完就宕機了或者磁盤壞了。但是也不用擔心這種情況,一是這種情況出現的概率非常低,二是Redis提供了修復AOF文件的工具。
當Redis服務器長時間運行時,AOF文件的內容會越來越多,文件的體積也會越來越大,為了解決這個問題,Redis提供了AOF文件重寫功能,消除一些冗余命令。
Redis提供了 BGREWRITEAOF命令來執行AOF重寫,AOF重寫不對舊AOF文件有依賴,而是通過查詢現有數據庫中的鍵值對的狀態來生成一個新的AOF文件,重寫動作在子進程中完成,生成一個新文件然后重命名替換掉老文件。在重寫的過程中,客戶端請求的新命令會追加到AOF重寫緩沖區中,子進程完成重寫之后,發送一個信號消息通知主進程把重寫緩沖區中的內容同步到重寫后的AOF文件中,這個過程會阻塞主進程。
通過設置appendfsync參數來設置AOF文件生成策略,它有三個可選值:
always,將AOF緩沖區的所有內容寫入并同步到AOF文件中,這種方式數據安全性最高,但是CPU消耗大。everysec,將AOF緩沖區中的所有內容寫入到AOF文件,如果上次同步AOF文件的時候距離現在超過一秒鐘,那么再次對AOF文件進行同步,并且這個同步操作由一個線程專門負責執行,數據安全性不如always,當服務器出現故障時會出現1s的數據空窗期,但是CPU消耗較always小。no,將AOF緩沖區中的所有內容寫入到AOF文件,但并不對AOF文件進行同步,何時同步由操作系統來決定。