徹底基於內存
,絕大部分請求是純粹的內存操做數據結構簡單
,對數據操做也簡單,Redis中的數據結構是專門爲各類場景設計的採用單線程
,避免了沒必要要的上下文切換和競爭條件,也不存在多進程或者多線程致使的切換而消耗CPU,不用去考慮各類鎖的問題,不存在加鎖釋放鎖操做,沒有由於可能出現死鎖而致使的性能消耗使用多路 I/O 複用模型
,非阻塞 IO「優勢:」redis
「缺點:」數據庫
簡介:
二進制安全能夠存儲的值:
字符串,整數或者浮點數,還有jpg圖片或者序列化對象操做:
對整個字符串或者字符串的其中一部分執行操做,對整數和浮點數執行自增或者自減操做應用場景:
作簡單的鍵值對緩存實際使用:
> set test cbuc
ok
----------------------------
> get test
"cbuc"
----------------------------
> del test
(integer) 1
----------------------------
>get test
(nil)
簡介:
鏈表(雙向鏈表)能夠存儲的值:
列表操做:
從兩端壓入或者彈出元素,對單個或者多個元素進行修改,只保留一個範圍內的元素應用場景:
最新消息排行;消息隊列實際使用:
> rpush test c1
(integer) 1
> rpush test c2
(integer) 2
> rpush test c2
(integer) 3
> lrange test 0 -1
1) "c1"
2) "c2"
3) "c3"
> lindex test 1
"c2"
> lpop test
"c1"
> lrange test 0 -1
"c2"
"c2"
簡介:
鍵值對集合,即編程語言中的map類型能夠存儲的值:
適合存儲對象,而且能夠像數據庫中的update同樣,只修改某一項的屬性值操做:
添加、獲取、移除單個鍵值對,獲取全部鍵值對,檢查某個鍵是否存在應用場景:
存儲、讀取、修改用戶屬性實際使用:
> hset test name cbuc
(integer) 1
> hset test age 23
(integer) 1
> hgetall test
1)"name"
2)"cbuc"
3)"age"
4)"23"
> hdel test age
(integer) 1
> hget test name
"cbuc"
> hgetall test
1)"name"
2)"cbuc"
簡介:
hash表實現,元素不重複能夠存儲的值:
無序集合操做:
添加、獲取、移除單個元素,檢查一個元素是否已經存在於集合中,計算交集、並集、差集從集合裏面隨機獲取元素應用場景:
共同好友;利用惟一性,統計訪問網站的全部IP實際使用:
> sadd test c1
(integer) 1
> sadd test c2
(integer) 1
> sadd test c1
(integer) 0
>smembers test
1)"c1"
2)"c2"
> sismember test c3
(integer) 0
> sismember test c1
(integer) 1
> srem test c1
(integer) 1
> smembers test
1)"c2"
簡介:
將 set 中的元素增長一個權重參數score,元素按score有序排列能夠存儲的值:
有序集合操做:
添加、獲取、刪除元素,根據分值範圍或者成員來獲取元素,計算一個鍵的排名應用場景:
排行榜;帶權重的消息隊列實際使用:
> zadd test 92 math
(integer) 1
> zadd test 88 english
(integer) 1
> zadd test 92 score
(integer) 1
> zrange test 0 -1 withscores
1)"english"
2)"88"
3)"math"
4)"92"
> zrangebyscore test 80 90 withscores
1)"english"
2)"88"
> zrem test english
(integer) 1
> zrange test 0 -1 withscores
3)"math"
4)"92"
「高級用法:」編程
BitMap
位圖是支持按 bit 位來存儲信息,能夠用來實現 布隆過濾器(BloomFilter)HyperLogLog
供不精確的去重計數功能,比較適合用來作大規模數據的去重統計,例如統計 UVGeospatial
能夠用來保存地理位置,並做位置距離計算或者根據半徑計算位置等。能夠用來實現附近的人,或者計算最優地圖路徑持久化就是把內存中的數據寫到磁盤中去,防止服務宕機了內存數據丟失。緩存
Redis提供兩種持久化機制:RDB快照(默認)和AOF(機制)安全
「RDB」服務器
❝RDB(Redis DataBase)是Redis中默認的持久化方式。按照必定的時間將內存的數據以快照的形式保存到磁盤中,會產生
❞dump.rdb
數據文件,能夠經過配置文件中的save參數來定義快照的週期。網絡
「原理:」
fork
和cow
。fork 是指 redis間隔一段時間會「fork」 一個子進程,子線程將數據寫到磁盤上一個臨時RDB文件中,當子進程寫完臨時文件後,將原來的RDB替換掉,這樣的好處是能夠「cow(copy-on-wirte)」「優勢:」數據結構
方便持久化
,只有一個文件 dump.rdb容災性好
,一個文件能夠保存到安全的磁盤中性能最大化
,fork 子進程來完成寫操做,讓主進程繼續處理命令,因此是IO最大化。使用單獨子進程來進行持久化,主進程不會進行任何IO操做,保證 redis 的高性能「缺點:」多線程
數據安全性低
,RDB是間隔一段時間來進行持久化,若是持久化之間 redis 發生故障,會發生數據丟失,因此這種方式更適合數據要求不嚴謹的時候用保存時間長
,若是數據量很大,保存快照的時間會很長「AOF」架構
❝AOF(Append-Only-File),是將 Redis 執行的每次寫命令記錄到單獨的日誌文件中,當重啓 Redis 會從新將持久化的日誌中文件恢復數據
❞
「原理:」 將寫命令添加到 AOF 文件(Append Only File)的末尾。使用AOF持久化須要設置同步選項,從而確保寫命令同步到磁盤文件上的時機。這是由於對文件進行寫入並不會立刻將內容同步到磁盤上,而是先存儲到緩衝區,而後由操做系統決定何時同步到磁盤。「同步選項:」
選項 | 同步頻率 |
---|---|
no | 讓操做系統決定什麼時候同步 |
always | 每一個寫命令都同步 |
everysec | 每秒同步一次 |
no:
並不能給服務器性能帶來多大的提高,並且也會增長系統奔潰時數據丟失的數量always:
嚴重減低服務器性能everysec:
這個選項比較合適,能夠保證系統奔潰時只會丟失一秒左右的數據,而且 Redis 每秒執行一次同步對服務器性能幾乎沒有任何影響隨着服務器寫請求的增多,AOF文件會愈來愈大。Redis提供了一種將AOF重寫的特性
「auto-aof-rewrite」,可以去除AOF文件中的冗餘寫命令
「優勢:」
數據安全
,AOF 持久化能夠配置 appendfsync 屬性中的always,沒進行一次寫命令操做就記錄到 AOF 文件中一次、一致性
,經過 append 模式寫文件,即便中途服務器宕機,能夠經過 redis-check-aof 工具解決數據一致性問題「缺點:」
二者比較
通常來講二者都會配置。若是單獨用 「RDB」 的話你會丟失不少數據,單獨用 「AOF」,你數據恢復沒有 「RDB」 來的快,若是系統出現問題的時候咱們能夠先用 「RDB」 恢復,而後用 「AOF」 補全數據。冷熱備份一塊兒用,才能保證高健壯性的系統。
定時刪除
每一個設置過時時間的 key 都須要建立一個定時器,到過時時間就會當即清除。該策略能夠當即清除過時的數據,對內存很友好;可是會佔用大量的CPU資源來處理過時的數據,從而影響緩存的響應時間和吞吐量惰性刪除
只有當訪問一個 key 時,纔會判斷該 key 是否已過時,是則刪除。該策略能夠最大化節省CPU資源,卻對內存很是不友好。極端狀況下可能出現大量的過時 key 沒有再次被訪問,從而不會被清除,佔用大量內存按期刪除
每隔必定時間,會掃描必定數量的 expires 字典中的 key,並清除其中已過時的 key。該策略是前二者的一個折中方法。經過調整定時掃描的時間間隔和每次掃描的限定耗時,能夠在不一樣狀況下使得CPU和內存資源達到最優的平衡效果。Redis 通常同時使用 惰性過時 和 按期過時 兩種過時策略
「設置過時時間的鍵空間選擇性移除」
volatile-lru:
嘗試回收最少使用的鍵使得新添加的數據有空間存放。volatile-random:
回收隨機的鍵使得新添加的數據有空間存放volatile-ttl:
優先回收存活時間較短的鍵使得新添加的數據有空間存放「全局的鍵空間選擇性移除」
allkeys-lru:
嘗試回收最少使用的鍵使得新添加的數據有空間存放。allkeys-random:
回收隨機的鍵使得新添加的數據有空間存放noeviction:
當內存達到限制而且客戶端嘗試執行,會返回錯誤Redis 事務的本質是經過 「MULTI」、「EXEC」、「WATCH」、「DISCARD」四個原語實現的。事務支持一次執行多個命令,一個事務中全部命令都會被序列化。在事務執行過程,會按照順序串行化執行隊列中的命令,其餘客戶端提交的命令請求不會插入到事務執行命令序列中。總結:
Redis 事務就是一次性、順序性、排他性的執行一個隊列中的一系列命令。
四個原語
EXPIRE 和 PERSIST 命令
緩存雪崩
是指緩存同一時間大面積的失效,因此,後面的請求都會落到數據庫上,形成數據庫短期內承受大量請求而崩掉解決方法:
緩存擊穿
是指緩存中沒有但數據庫中有的數據(通常是緩存時間到期),這時因爲併發用戶特別多,同時讀緩存沒讀到數據,又同時去數據庫去取數據,引發數據庫壓力瞬間增大解決方法:
緩存穿透
是指緩存和數據庫中都沒有的數據,致使全部的請求都落到數據庫上,形成數據庫短期內承受大量請求而崩掉解決方法:
單機的 Redis,可以承載的 QPS 大概在上萬到幾萬不等,對於緩存來講,通常都是用來支撐「讀高併發」的。若是一臺機器讀寫合一的那會很容易發生問題。所以會採用主從架構,讓 master 去處理寫操做,而後把數據同步到 slave 上,slave 負責讀操做。這樣就會分發掉大量的請求,並且在擴容的時候還能夠輕鬆實現水平擴容。當啓動一臺 slave 的時候,它會發送一個
psync
命令到 master ,若是是第一次同步,主節點會作一次「bgsave」,並同時將後續修改操做記錄到內存「buffer」,待完成後將「RDB」文件全量同步到複製節點,複製節點接收完成後將「RDB」鏡像加載到內存而後寫入本地磁盤。處理完成後,再通知主節點將期間修改的操做記錄同步到複製節點進行重放就完成了同步過程。後續的增量數據經過「AOF」日誌同步便可,相似於數據庫的「binlog」。
簡單來講就是先拿setnx來爭搶鎖,搶到以後,再用expire給鎖加一個過時時間防止鎖忘記了釋放
SETNX 是【SET if Not eXists】(若是不存在,則 SET)的簡寫。當且僅當 key 不存在,將 key 的值設爲 value。若給定的 key 已經存在,則 SETNX 不作任何動做。返回值:設置成功,返回 1 。設置失敗,返回 0 。
Redis可使用主從同步,從從同步。第一次同步時,主節點會作一次「bgsave」,並同時將後續修改操做記錄到內存「buffer」,待完成後將「RDB」文件全量同步到複製節點,複製節點接收完成後將「RDB」鏡像加載到內存而後寫入本地磁盤。處理完成後,再通知主節點將期間修改的操做記錄同步到複製節點進行重放就完成了同步過程。後續的增量數據經過「AOF」日誌同步便可,相似於數據庫的「binlog」。
Redis Sentinel(哨兵)着眼於高可用,在master 宕機時會自動將slave提高爲master,繼續提供服務。Redis Cluster(集羣)着眼於擴展性,在單個redis內存不足時,使用Cluster進行分片存儲。「選主策略:」
哨兵必須用三個實例去保證本身的健壯性,哨兵 + 主從 「並不能保證數據不丟失」 ,可是能夠保證集羣的高可用。
工做原理:
何爲腦裂:
❝Redis 的集羣腦裂是指由於網絡問題,致使 redis master 節點跟 redis slave 節點和 sentinel 集羣處於不用的網絡分區,此時由於 sentinel 集羣沒法感知到 master 的存在,因此將 slave 節點提高爲 master 節點。此時存在兩個不一樣的 master 節點,就像是一個大腦分裂成了兩個。這時若是客戶端還在基於原來的 master 節點繼續寫入數據,那麼新的 master 節點將沒法同步這些數據,當網絡問題解決以後,sentinel集羣就會將原先的 master 節點降爲 slave 節點,此時再重新的 master 中同步數據,將會形成大量的數據丟失
❞
解決:
min-replicas-to-write 3 # 表示鏈接到 master 的最少slave數量
min-replicas-max-lag 10 # 表示 slave 鏈接到 master 的最大延遲時間
按照上面配置,要求至少3個slave節點,且數據複製和同步的延遲不能超過10秒,不然的話 master 就會拒絕寫請求,配置了這兩個參數以後,若是發生集羣腦裂,原先的 master 節點接收到客戶端的寫入請求會拒絕,就能夠減小數據同步以後的數據丟失