有時候須要將原先存有的大量數據遷移到新的redis實例,redis提供一些方案可讓這個過程更快linux
經過redis-cli一個一個操做太慢redis
經過pipeline操做,又會阻塞服務器算法
大數據量插入時,先按官網提到的協議生成對應格式的文本文件,而後使用redis-cli的管道模式批量導入緩存
將數據分佈到不一樣的redis實例安全
範圍分片: 例如根據用戶id的區間決定數據劃分到哪一個實例服務器
hash分片: 先使用哈希函數求得哈希值,再經過取模根據結果例如介於0-3之間決定數據存儲在哪一個實例.少數客戶端在這基礎上實現了連續哈希網絡
客戶端分片: 在客戶端就決定好讀寫的實例數據結構
代理分片: 客戶端發送請求到代理,由代理決定實際的redis實例並返回響應給客戶端,例如Twemproxy就應用這種模式異步
查詢路由: 客戶端發送請求到隨機的一個redis實例,redis再轉發請求到正確的節點.Redis Cluster 使用了這種模式,不一樣的是將客戶端的鏈接重定向到正確的redis實例上而不是直接轉發.分佈式
分片後,不能直接對多個key一次操做
事務不能對多個key操做
像有序集合數據集被包含在一個大key中沒法對內部key進行分片
增長操做複雜度,例如備份數據,須要整合各個實例的持久化文件
增長或減小容量比較複雜,Redis Cluster會從新平衡數據,當增長或者移除節點時.而使用客戶端或代理分片方式則難以作到,Pre-sharding技術經過遷移實例的方式實現
已經有多種庫實現了分佈式redis鎖管理,具體https://redis.io/topics/distlock
安全性: 互斥,同一個時刻只能有一個客戶端擁有鎖
死鎖的釋放: 例如當客戶端鎖住資源發生崩潰而其餘客戶端獲取鎖時
故障容錯: 只要大部分redis節點存活,客戶端就能進行正常的獲取釋放鎖
客戶端A從主庫獲取對資源a的鎖
對key的寫入發送到從庫前,主庫崩潰
從庫被提高爲主庫
客戶端B從主庫獲取對資源a的鎖,此時就違背了安全性原則
使用setnx設置key的值,值必須全局惟一,釋放鎖時檢查key是否存在,值是否與預期一致(第二條解釋)
當客戶端獲取的鎖的key帶有過時時間.直接使用del最後釋放鎖的方式,若是過程當中由於一些耗時操做致使key過時,此時其餘客戶端可以獲取到鎖,則最後del釋放鎖會把其餘客戶端的鎖也釋放.因此經過設置鎖key的值做爲簽名並在最後使用del釋放時作檢查
使鎖key的值惟一可使用rc4根據具體信息生成對應隨機字符串
假設有5個redis獨立主庫
客戶端先獲取當前的時間毫秒級
順序獲取5個實例的鎖,一樣的key名和隨機值.
客戶端獲取鎖時,會設置一個相對鎖過時時間很小的超時時間,若是一個實例獲取不到鎖超時則馬上獲取下一個實例的
順序獲取實例鎖時,鎖的有效時間會逐漸遞減,以最後獲取實例的鎖有效時間爲準,最後每一個實例鎖的過時時間會是一致
若是已經存在N/2+1實例的鎖key或者鎖過時,則放棄獲取全部實例的鎖的操做.這就能夠實現互斥原則,當一個客戶端獲取成功後,其餘客戶端能夠由於沒有獲取到足夠實例的鎖而放棄
該算法基於假設全部機器和進程的時鐘頻率一致或相對於鎖過時時間產生的偏差能夠忽略不計
當獲取鎖失敗時,須要及時釋放已獲取的部分實例鎖,能夠避免須要等到key過時才能再次獲取鎖
文檔對安全性和可用性進行了討論,具體能夠看文檔
提升鎖的性能能夠經過使用非阻塞模式發送全部命令,再讀取檢查
須要設置持久化參數fsync=always避免斷電或其餘災難後重啓key丟失問題
算法對於斷電或災難重啓後的實例再也不參與現有活躍的鎖.若是客戶端A獲取到3/5實例鎖,而重啓新增了一個實例,此時存在N/2+1實例的鎖key條件不存在,其餘客戶端又能夠獲取鎖了.解決問題的方法時,重啓後保持一段不可用時間大於其餘鎖的過時時間.這裏會引入一個問題就是若是多個實例重啓,在這個不可用期間,意味着新的獲取鎖可能失敗.
擴展能夠考慮可重入鎖的實現
key空間報告經過發佈訂閱模式實現,默認不開啓,能夠經過配置文件開啓
接收對key產生實際操做的事件
redis主要經過key來獲取數據,利用redis的一些數據結構能夠建立二級索引
經過有序集合的分值對數據對象進行索引
常見的操做爲,hash結構存儲數據對象集合,有序集合對數據對象建立索引
若是能將多維數據轉爲線性,則能夠利用有序集合對數據進行list索引
兩個分值同樣的,則經過C函數memcmp比較
ZRANGEBYLEX能夠對值進行檢索,包括或排除,能夠利用在自動補全場景
能夠再給值加上頻率條件
考慮大小寫條件時,能夠按小寫:頻率:大寫的方式存儲值
使用組合索引,實際就是將多個字段信息組合後存儲爲有序集合
只要找到一種規則就能夠合理利用ZRANGEBYLEX對數據進行查詢
主庫發送將命令實時發送給從庫
主從鏈接斷開時會重連,並找回鏈接斷開期間主庫命令從新同步
若是找回斷開期間部分的命令失敗,則執行所有同步,具體由主庫發送快照給從庫,而後繼續保持同步
從庫複製異步進行,從庫返回確認也是異步進行
若是從庫落後主庫,能夠根據配置決定此時從庫是否還可使用舊的數據
主從複製的一個好處是能夠避免主庫持久化老是須要將數據寫入磁盤,能夠經過從庫複製實時保存.然而須要注意的是,若是重啓主庫,主庫數據集爲空,從庫同步複製主庫時,從庫數據也會被清空
建議在主從都開啓持久化,或者若是不開啓持久化則要避免重啓機器後自動重啓服務
每個主庫有一個replication id標識,對每一個發送給從庫的命令會有一個下標.若是從庫斷連後重連,則會告訴主庫最後一個下標,並從該下標開始追趕執行命令同步主庫
重新同步時,主庫會開啓一個存儲進程生成RDB文件(寫入磁盤),並緩存新接收的寫命令.將RDB文件發送給從庫,從庫加載RDB文件到內存中,並接收主庫緩存的命令而後繼續同步
從庫不會對key作expire操做,當主庫key過時時執行del操做時發送到從庫,從庫執行
當訪問從庫已過時key時,由於主庫的延遲操做,從庫根據自身時鐘作出判斷報告該key不存在
主庫執行Lua腳本時,時間被凍結,因此腳本必須同步到從庫執行保證一致效果
RDB: 經過對某個時間點數據集存儲爲快照文件
AOF: 記錄每個寫操做,經過重放方式初始化數據
能夠在同一個實例中同時使用這兩種模式,重啓實例時,AOF模式用於重新初始化數據
爲所欲爲對某個時間點的數據進行備份
適合用於災難恢復
經過子進程完成備份,而父進程不用磁盤IO,不影響其餘命令的進行
重啓初始化數據更快
派生子進程,在數據集很大時會比較耗時.頻繁備份對性能有必定損耗
能夠多種文件同步策略,每秒記錄或每一個寫命令時記錄,持續性更好
是一個只加文件,無需定位,容易修復
若是AOF文件太大時,redis會自動生成新的文件並切換到新的文件
若是不當心執行了FLUSHALL命令,只要尚未新的命令寫入,中止實例.並將最後一個命令刪除後重啓redis就能夠了
redis會避免RDB和AOF的進程在同一時刻進行
建議設置定時任務生成每一個小時的RDB文件放在一個文件夾和生成天天的RDB文件放在另外一個文件夾
定時任務每次執行,清除比較老的RDB文件
天天轉移RDB文件
網絡安全策略,將redis運行在虛擬化的linux實例避免直接暴露,外部沒法經過防火牆鏈接redis,客戶端經過環回地址與對應端口通訊
安全模式: 從3.2.0版本開始,若是在配置上容許綁定全部端口,並且外部訪問無需密碼時會進入安全模式,只有經過環回地址的纔可以正常訪問,其餘的客戶端返回錯誤
認證功能: 密碼應該設置足夠長
數據加密: redis並不支持,不過能夠再加一層SSL代理.redis推薦Spiped作對稱加密
設置一些命令不可用
NoSQL注入: 注意從不可信賴來源獲取可能爲Lua腳本做爲字符串的問題