Redis簡析

原文地址:redis簡析html

1、Redis是什麼?

Redis是一個基於C語言開發的開源的高性能內存數據庫,通常用做緩存和消息中間件,屬於NoSQL的一種。
做爲內存數據庫,其優點有:
一、性能強悍,數據存儲在內存中,讀寫速度很是快,支持併發10W QPS
二、單進程單線程,是線程安全的,採用IO多路複用機制;
三、豐富的數據類型,支持字符串(Binary-safe strings),哈希(Hashes),列表(Lists),集合(Sets),有序集合(Sorted sets)等;
四、支持數據持久化。可將內存中的數據保存在磁盤中,重啓時加載;
五、主從複製,哨兵,高可用;
六、能夠用做分佈式鎖;
七、能夠做爲消息中間件使用,支持發佈訂閱。redis

2、經常使用的5種數據類型

redis使用redisObject對象來表示全部的key和value:
redisObject.jpg
redisObject中type表示value對象具體是哪一種數據類型,encoding是不一樣數據類型在redis中的存儲方式。如type=string表示value存儲的是一個普通字符串,那麼encoding能夠適raw或int。算法

一、string

string是redis是最基本、最經常使用的數據類型,和memcached的k-v結構相似。value不只能夠適字符串,也能夠是數字。string類型是二進制安全的,就是說redis的string類型能夠包含任何數據,好比圖片或者序列化對象。string類型的value最大能存儲512M。數據庫

二、hash

hash是一個鍵值(k-v)的集合。redis的hash是一個string類型的key和value的映射表,hash特別適合存儲對象。經常使用的命令:hget,hset,hgetall等。api

三、list

list列表是簡單的字符串列表,按照插入順序排序。能夠添加一個元素到列表的頭部(左邊)或尾部(右邊)。經常使用的命令:lpush,rpush,lpop,rpop,lrange(獲取列表片斷)等。
應用場景:list是Redis中最重要的數據結構之一,如社交網站的關注列表,粉絲列表等均可以用list來實現。
數據結構:list屬於鏈表,能夠用來作消息隊列。Redis提供了list的push和pop操做,還提供了操做某一段的api,能夠直接查詢或刪除某一段的元素。
實現方式:Redis list的實現是一個雙向鏈表,支持反向查找和遍歷。緩存

四、set

set是string類型的無序集合。集合經過hash table實現,set中的元素無序不重複。經常使用的命令:sadd,spop,smembers、sunion等。
應用場景:Redis set對外提供的功能和list同樣是一個列表,特別之處在於set是自動去重的,並且set提供了判斷某個成員是否在一個set集合中的方法。安全

五、zset

zset和set同樣是string類型元素的集合,且不容許重複的元素,經過score參數來排序,經常使用的命令:zadd,zrange,zrem,zcard等。
應用場景:有序集合sorted set經過用戶提供的score參數來爲成員排序,而且是插入有序的,即自動排序。當須要一個有序且不重複的集合列表時,能夠選擇有序集合結構。和set相比,sorted set關聯了一個double類型權重的參數score,使得集合中的元素可以按照score進行有序排列,Redis正是經過分數來爲集合中的成員進行從小到大的排序。
實現方式:Redis sorted set內部使用HashMap和跳躍表(SkipList)來保證數據的存儲和有序,HashMap裏存放的是成員到score的映射,而跳躍表中存放的是全部的成員,排序依據是HashMap裏存的score,使用跳躍表的結構能夠得到比較高的查找效率,而且在實現上比較簡單。服務器

數據類型與應用場景總結:

類型 簡介 特性 場景
string(字符串) 二進制安全 能夠包含任何數據,如圖片、序列化對象
hash(哈希字典) 鍵值對集合 適合存儲對象,而且能夠像數據庫中的update同樣,只修改某一項屬性值 存儲,讀取,修改用戶屬性
list(列表) 鏈表(雙向鏈表) 增刪快,提供了操做某一元素的api 最新消息排行;消息隊列
set(集合) hash表實現,元素無序不重複 添加,刪除,查找的複雜度都是O(1),提供了求交集,並集,差集的操做 共同好友;利用惟一性,統計訪問網站的全部ip
sort set(有序集合) 將set中的元素增長一個權重參數score,元素按score有序排列 數據插入集合時,已經進行了自然排序 排行榜;帶權重的消息隊列

3、緩存問題

一、緩存和數據庫數據一致性問題。

分佈式環境下,不可避免的存在數據庫和緩存數據不一致的問題,若是項目要求數據必須是強一致性的,那麼就不要使用緩存。咱們只能採起合理的策略去下降緩存和數據庫間數據不一致的機率,而沒法保證絕對一致。合理的策略包含合適的緩存更新策略,更新數據庫後及時更新緩存、緩存失敗時增長重試機制。網絡

二、緩存雪崩

若是緩存在一段時間內失效,發生大量的緩存穿透,全部的查詢都落在數據庫上,形成緩存雪崩。
因爲原有緩存失效,因此新緩存未到期間,全部本來應該訪問緩存的請求都去查詢數據庫了,對數據庫的CPU和內存形成巨大壓力,嚴重的會形成數據庫宕機。
解決方案:
a、加鎖排隊:用mutex鎖(互斥鎖)解決,用Redis的setnx去設置一個key,當返回成功時,進行加載數據庫的操做並設置緩存,不然就重試獲取緩存。
b、緩存預熱:緩存預熱就是系統上線前,將相關的緩存數據直接加載到緩存系統中,這樣能夠避免在用戶請求的時候直接查詢數據庫而後回寫緩存的問題,用戶直接能夠查詢到緩存。
c、雙層緩存:C1爲原始緩存,C2爲拷貝緩存,C1失效時,能夠訪問C2,C2的緩存失效時間設置爲長期。
d、定時更新緩存:對時效性要求不高的緩存,能夠採用定時任務去更新或移除緩存。
e、設置不一樣的過時時間,避免同一時間點緩存集體失效。【此方式方便高效】數據結構

三、緩存擊穿

在高併發的系統中,大量的請求同時查詢一個key時,此時這個key正好失效了,就會致使請求全都打到數據庫上面去,這種現象就是緩存擊穿。
緩存擊穿和緩存雪崩有點像,緩存雪崩是由於大面積的緩存失效,打崩了數據庫,而緩存擊穿則是指一個key很是熱點,在不停的扛着大量的請求,當這個key失效的瞬間,持續的請求直接打到數據庫上。
解決方案:
設置熱點數據永不過時,或者加上互斥鎖,請求擊穿緩存要查詢數據庫時則獲取鎖而後去查,其餘請求獲取不到鎖則等待,而後嘗試請求緩存。

四、緩存穿透

緩存穿透是指緩存和數據庫中都沒有的數據,卻不斷有請求想要獲取。好比:不斷有請求獲取id<=0的數據,這樣緩存沒有,進入數據庫查詢,數據庫雖然也沒有,可是不斷的去查詢返回,致使數據庫壓力增大,可能致使數據庫宕機。
解決方案:
a、基本校驗:接口層增長校驗,如用戶鑑權,參數校驗(如id是否大於0),不知足直接返回。
b、緩存空值:若查詢返回爲空(不管是數據真的不存在仍是系統故障),咱們仍然緩存空值,並設置其過時時間較短(通常不超過5分鐘)。這樣就避免每次請求都穿透緩存直達數據庫。
c、採用布隆過濾器(BloomFilter)
原理是利用高效的數據結構和算法快速判斷查詢key是否存在數據庫中,不存在則直接返回空,存在則去查數據庫並刷新緩存。

4、Redis的單線程

Redis是單進程單線程的模型,由於Redis徹底是基於內存的操做,CPU不是Redis的瓶頸,Redis的瓶頸是機器內存的大小或者網絡帶寬。既然單線程容易實現,並且CPU不會成爲瓶頸,那麼採用單線程的方案比多線程少不少麻煩(如各類鎖)。

一、爲什麼採用單線程還這麼快?

a、Redis徹底基於內存,絕大部分請求是純粹的內存操做,很是迅速,數據存在內存中,相似於HashMap,而HashMap的優點就是查詢和操做的時間複雜度是O(1)。
b、數據結構簡單,對數據的操做也簡單。
c、採用單線程,避免多線程致使的CPU切換和各類加鎖釋放鎖的操做和死鎖問題。
d、使用多路複用IO模型,非阻塞IO。四大點,搞懂Redis到底快在哪

5、Redis和Memcached的區別

一、存儲方式上:memcached數據所有存在內存中,斷電即丟失,數據不能超過內存大小。Redis有部分數據存在硬盤上,保證數據的持久性。
二、數據類型上:memcached只有k-v數據類型,Redis支持多種數據結構。
三、使用底層模型不一樣:它們之間底層實現方式以及與客戶端之間通訊的應用協議不同。Redis直接本身構建了VM機制,由於通常的系統調用系統函數時,會浪費必定的時間去移動和請求。
四、value的大小:Redis可達1GB,memcached只有1MB。

6、Redis的淘汰策略

策略 描述
volatile-lru 從已設置過時時間的kv集合中,優先對最近少使用(less recently used)的數據淘汰
volitile-ttl 從已設置過時時間的kv集合中,優先對剩餘時間短(time to live)的數據淘汰
volitile-random 從已設置過時時間的kv集合中,隨機選擇數據淘汰
allkeys-lru 從全部kv集合中,優先對最近最少使用(less recently used)的數據淘汰
allkeys-random 從全部kv集合中,隨機算則數據淘汰
noeviction 不淘汰策略,若超過最大內存,返回錯誤信息
volatitle-lfu (4.0+)從已設置過時時間的kv集合中,優先對最近頻率低(less frequency use)的數據淘汰
allkeys-lfu (4.0+)從全部的kv集合中,優先對最近頻率低(less frequency use)的數據淘汰

7、Redis的持久化

一、持久化機制

Redis爲了保證效率,數據緩存在內存中,可是會週期性的把更新的數據寫入磁盤或者把修改的操做寫入追加的記錄文件中,以保證數據的持久化。
Redis的持久化策略有兩種:
一、RDB:快照形式是直接把內存中的數據保存到一個dump的文件中,定時保存。
二、AOF:把全部的對Redis的服務器進行修改的命令集合都追加在一個文件中。
Redis默認是快照RDB的持久化方式。
當Redis重啓時,它會優先使用AOF文件來還原數據集,由於AOF文件保存的數據集一般比RDB文件所保存的數據集更完整。持久化詳解

二、RDB

默認Redis是會以快照RDB的形式將數據持久化到磁盤的一個二進制文件dump.rdb中。

工做原理

當Redis須要作持久化時,Redis會fork一個子進程,子進程將數據寫到磁盤上一個臨時的RDB文件中,當子進程完成臨時文件後,將原來的RDB替換掉,這樣的好處是能夠copy-on-write。

RDB的優缺點

優勢:
RDB文件緊湊,適合用於備份。如能夠根據業務狀況在不一樣的時間點對Redis數據進行RDB備份,這樣遇到問題時能夠還原到不一樣時間版本的數據,很是適合容災恢復。
缺點:
若須要儘可能避免在服務器故障時丟失數據,那麼RDB不合適。

三、AOF

使用AOF作持久化,每個寫命令都經過write函數追加寫到appendonly.aof中。

appendonly yes
appendfsync always #每次有數據修改發生時都會寫入AOF文件
appendfsync everysec #每秒同步一次,該策略爲AOF的缺省策略

AOF能夠作到全程持久化,只須要在配置中開啓appendonly yes。這樣redis每執行一個修改數據的命令,都會把它添加到AOF文件中,當redis重啓時,將會讀取AOF文件進行重放,恢復到Redis關閉前的樣子。
優勢:
使用AOF的優勢是會讓Redis變得很是耐久,能夠設置不一樣的fsync策略,AOF的默認策略是每秒fsync一次,在這種配置下,就算髮生故障停機,也最多丟失一秒鐘的數據。
缺點:
缺點是對於相同的數據集來講,AOF的文件體積一般大於RDB文件的體積,根據所使用的fsync策略,AOF的速度可能慢於RDB。

四、該用AOF仍是RDB呢?

若業務能夠承受幾分鐘內數據的丟失,那麼能夠只使用RDB持久化數據。AOF將Redis執行的每一條命令追加到磁盤中,處理巨大的寫入會下降Redis的性能。
定時生成RDB快照很是便於進行數據庫備份,而且RDB恢復數據集的速度也要比AOF恢復的速度快。
固然,Redis支持同時開啓RDB和AOF,系統重啓後,Redis會優先使用AOF來恢復數據,這樣丟失的數據最少。

8、主從複製

Redis單節點存在單點故障問題,爲了解決單點問題,通常都須要對Redis配置從節點,而後使用哨兵來監聽主節點的存活狀態,若是主節點掛掉,從節點能繼續提供緩存功能。

一、Redis主從複製的原理

主從配置結合哨兵模式能解決單點故障問題,提升Redis可用性。從節點僅提供讀操做,主節點提供寫操做。對於讀多寫少的情況,可給主節點配置多個從節點,從而提升響應效率。
關於複製過程:
一、從節點執行slaveof[masterIP][masterPort],保存主節點信息;
二、從節點的定時任務發現主節點信息,創建和主節點的socket鏈接;
三、從節點發送ping信號,主節點返回pong,兩邊互通;
四、創建鏈接後,主節點將全部數據發送給從節點(數據同步);
五、主節點把當前數據同步給從節點,便完成了複製的創建過程。接下來,主節點就會持續的把命令發送給從節點,保證主從一致性。

二、主從數據同步過程

Redis2.8以前使用sync[runID][offset]同步命令,Redis2.8以後使用psync[runID][offset]命令。Redis集羣和MySQL主從同步
兩種方式的不一樣在於,sync命令僅支持全量複製過程,psync支持全量和複製。
其中:
runID:每一個Redis節點啓動都會生成惟一的uuid,每次Redis重啓後,runID都會發生變化。
offset:主節點和從節點都各自維護本身的主從複製偏移量offset,當主節點有寫入命令時,offset=offset+命令的字節長度。從節點在收到主節點發送的命令後,也會增長本身的offset,並把本身的offset發送給主節點,這樣主節點同時保存本身的offset和從節點的offset,經過對比offset來判斷主從節點數據是否一致。
repl_backlog:保存在主節點上的一個固定長度的先進先出隊列,默認是1MB,名爲複製積壓緩衝區。(可設置)
Redis主從同步
主節點發送數據給從節點過程當中,不只會把寫命令發送給從節點,還會降寫命令入隊到複製積壓緩衝區內,主從服務器重連時,從服務器發送同步命令和offset,主服務器檢測到offset在複製積壓緩衝區內,則開始部分複製,不然全量複製。
主服務器發送寫命令:
redis-fzjyhcq.png

psync執行流程:
redis-zc.jpg
從節點發送psync[runID][offset]命令,主節點有三種響應:
一、fullresync:第一次鏈接,進行全量複製
二、continue:進行部分複製
三、err:不支持psync命令,進行全量複製

https://mp.weixin.qq.com/s/M9...

相關文章
相關標籤/搜索