初識redis基礎講解與介紹

redis講解與介紹

Redis介紹:
        Redis 是一個開源(BSD許可)的,內存中的數據結構存儲系統,它可以用作數據庫、緩存和消息中間件。 它支持多種類型的數據結構,如 字符串(strings)散列(hashes)列表(lists)集合(sets)有序集合(sorted sets) 與範圍查詢, bitmapshyperloglogs 地理空間(geospatial) 索引半徑查詢。 Redis 內置了 複製(replication)LUA腳本(Lua scripting)LRU驅動事件(LRU eviction)事務(transactions) 和不同級別的 磁盤持久化(persistence), 並通過 Redis哨兵(Sentinel)和自動 分區(Cluster)提供高可用性(high availability)。
 
 
爲什麼使用Redis?

 高性能:

        假如用戶第一次訪問數據庫中的某些數據。這個過程會比較慢,因爲是從硬盤上讀取的。將該用戶訪問的數據存在緩存中,這樣下一次再訪問這些數據的時候就可以直接從緩存中獲取了。操作緩存就是直接操作內存,所以速度相當快。如果數據庫中的對應數據改變的之後,同步改變緩存中相應的數據即可!

 
 高併發:
  直接操作緩存能夠承受的請求是遠遠大於直接訪問數據庫的,所以我們可以考慮把數據庫中的部分數據轉移到緩存中去,這樣用戶的一部分請求會直接到緩存這裏而不用經過數據庫。

redis 的線程模型

    redis 內部使用文件事件處理器 file event handler,這個文件事件處理器是單線程的,所以 redis 才叫做單線程的模型。它採用 IO 多路複用機制同時監聽多個 socket,根據 socket 上的事件來選擇對應的事件處理器進行處理。  
  文件事件處理器的結構包含 4 個部分:  
  1.   多個 socket
  2.   IO 多路複用程序
  3.   文件事件分派器
  4.   事件處理器(連接應答處理器、命令請求處理器、命令回覆處理器)
  多個 socket 可能會併發產生不同的操作,每個操作對應不同的文件事件,但是 IO 多路複用程序會監聽多個 socket,會將 socket 產生的事件放入隊列中排隊,事件分派器每次從隊列中取出一個事件,把該事件交給對應的事件處理器進行處理。

redis 常見數據結構以及使用場景分析  

  1.String

  常用命令: set,get,decr,incr,mget 等。

  String數據結構是簡單的key-value類型,value其實不僅可以是String,也可以是數字。 常規key-value緩存應用; 常規計數:微博數,粉絲數等。

  2.Hash

  常用命令: hget,hset,hgetall 等。

  hash 是一個 string 類型的 field 和 value 的映射表,hash 特別適合用於存儲對象,後續操作的時候,你可以直接僅僅修改這個對象中的某個字段的值。 比如我們可以 hash 數據結構來存儲用戶信息,商品信息等等。比如下面我就用 hash 類型存放了我本人的一些信息:
 
key=JavaUser293847
value={  
“id”: 1,   
“name”: “SnailClimb”,   
“age”: 22,   
“location”: “Wuhan, Hubei”
}

 3.List  

  常用命令: lpush,rpush,lpop,rpop,lrange等  

  list 就是鏈表,Redis list 的應用場景非常多,也是Redis最重要的數據結構之一,比如微博的關注列表,粉絲列表,消息列表等功能都可以用Redis的 list 結構來實現。  
  Redis list 的實現爲一個雙向鏈表,即可以支持反向查找和遍歷,更方便操作,不過帶來了部分額外的內存開銷。  
  另外可以通過 lrange 命令,就是從某個元素開始讀取多少個元素,可以基於 list 實現分頁查詢,這個很棒的一個功能,基於 redis 實現簡單的高性能分頁,可以做類似微博那種下拉不斷分頁的東西(一頁一頁的往下走),性能高。

  4.Set  

  常用命令: sadd,spop,smembers,sunion 等  

  set 對外提供的功能與list類似是一個列表的功能,特殊之處在於 set 是可以自動排重的。  
  當你需要存儲一個列表數據,又不希望出現重複數據時,set是一個很好的選擇,並且set提供了判斷某個成員是否在一個set集合內的重要接口,這個也是list所不能提供的。可以基於 set 輕易實現交集、並集、差集的操作。  
  比如:在微博應用中,可以將一個用戶所有的關注人存在一個集合中,將其所有粉絲存在一個集合。Redis可以非常方便的實現如共同關注、共同粉絲、共同喜好等功能。這個過程也就是求交集的過程,具體命令如下:
 
sinterstore key1 key2 key3     將交集存在key1內

 5.Sorted Set  

  常用命令: zadd,zrange,zrem,zcard等  

  和set相比,sorted set增加了一個權重參數score,使得集合中的元素能夠按score進行有序排列。  
  舉例: 在直播系統中,實時排行信息包含直播間在線用戶列表,各種禮物排行榜,彈幕消息(可以理解爲按消息維度的消息排行榜)等信息,適合使用 Redis 中的 Sorted Set 結構進行存儲。

redis 設置過期時間

  Redis中有個設置時間過期的功能,即對存儲在 redis 數據庫中的值可以設置一個過期時間。作爲一個緩存數據庫,這是非常實用的。如我們一般項目中的 token 或者一些登錄信息,尤其是短信驗證碼都是有時間限制的,按照傳統的數據庫處理方式,一般都是自己判斷過期,這樣無疑會嚴重影響項目性能。  
  我們 set key 的時候,都可以給一個 expire time,就是過期時間,通過過期時間我們可以指定這個 key 可以存活的時間。  
  如果假設你設置了一批 key 只能存活1個小時,那麼接下來1小時後,redis是怎麼對這批key進行刪除的?
  定期刪除+惰性刪除。
  通過名字大概就能猜出這兩個刪除方式的意思了。
  • 定期刪除:redis默認是每隔 100ms 就隨機抽取一些設置了過期時間的key,檢查其是否過期,如果過期就刪除。注意這裏是隨機抽取的。爲什麼要隨機呢?你想一想假如 redis 存了幾十萬個 key ,每隔100ms就遍歷所有的設置過期時間的 key 的話,就會給 CPU 帶來很大的負載!
  • 惰性刪除 :定期刪除可能會導致很多過期 key 到了時間並沒有被刪除掉。所以就有了惰性刪除。假如你的過期 key,靠定期刪除沒有被刪除掉,還停留在內存裏,除非你的系統去查一下那個 key,纔會被redis給刪除掉。這就是所謂的惰性刪除,也是夠懶的哈!
  但是僅僅通過設置過期時間還是有問題的。我們想一下:如果定期刪除漏掉了很多過期 key,然後你也沒及時去查,也就沒走惰性刪除,此時會怎麼樣?如果大量過期key堆積在內存裏,導致redis內存塊耗盡了。怎麼解決這個問題呢? redis 內存淘汰機制。

redis 內存淘汰機制(MySQL裏有2000w數據,Redis中只存20w的數據,如何保證Redis中的數據都是熱點數據?)

  redis 配置文件 redis.conf 中有相關注釋,我這裏就不貼了,大家可以自行查閱或者通過這個網址查看:http://download.redis.io/redis-stable/redis.conf

  redis 提供 6種數據淘汰策略:

  1.   volatile-lru:從已設置過期時間的數據集(server.db[i].expires)中挑選最近最少使用的數據淘汰
  2.   volatile-ttl:從已設置過期時間的數據集(server.db[i].expires)中挑選將要過期的數據淘汰
  3.   volatile-random:從已設置過期時間的數據集(server.db[i].expires)中任意選擇數據淘汰
  4.   allkeys-lru:當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的key(這個是最常用的)
  5.   allkeys-random:從數據集(server.db[i].dict)中任意選擇數據淘汰
  6.        no-eviction:禁止驅逐數據,也就是說當內存不足以容納新寫入數據時,新寫入操作會報錯。這個應該沒人使用吧!
  4.0版本後增加以下兩種:
  7.         volatile-lfu:從已設置過期時間的數據集(server.db[i].expires)中挑選最不經常使用的數據淘汰
  8.         allkeys-lfu:當內存不足以容納新寫入數據時,在鍵空間中,移除最不經常使用的key

redis 持久化機制(怎麼保證 redis 掛掉之後再重啓數據可以進行恢復)

  很多時候我們需要持久化數據也就是將內存中的數據寫入到硬盤裏面,大部分原因是爲了之後重用數據(比如重啓機器、機器故障之後恢復數據),或者是爲了防止系統故障而將數據備份到一個遠程位置。  
  Redis不同於Memcached的很重一點就是,Redis支持持久化,而且支持兩種不同的持久化操作。Redis的一種持久化方式叫快照(snapshotting,RDB),另一種方式是隻追加文件(append-only file,AOF)。這兩種方法各有千秋,下面我會詳細這兩種持久化方法是什麼,怎麼用,如何選擇適合自己的持久化方法。  
  快照(snapshotting)持久化(RDB)  
  Redis可以通過創建快照來獲得存儲在內存裏面的數據在某個時間點上的副本。Redis創建快照之後,可以對快照進行備份,可以將快照複製到其他服務器從而創建具有相同數據的服務器副本(Redis主從結構,主要用來提高Redis性能),還可以將快照留在原地以便重啓服務器的時候使用。  
  快照持久化是Redis默認採用的持久化方式,在redis.conf配置文件中默認有此下配置:
save 900 1 #在900秒(15分鐘)之後,如果至少有1個key發生變化,Redis就會自動觸發BGSAVE命令創建快照。
save 300 10 #在300秒(5分鐘)之後,如果至少有10個key發生變化,Redis就會自動觸發BGSAVE命令創建快照。
save 60 10000 #在60秒(1分鐘)之後,如果至少有10000個key發生變化,Redis就會自動觸發BGSAVE命令創建快照。

  AOF(append-only file)持久化

  與快照持久化相比,AOF持久化 的實時性更好,因此已成爲主流的持久化方案。默認情況下Redis沒有開啓AOF(append only file)方式的持久化,可以通過appendonly參數開啓:
appendonly yes
  開啓AOF持久化後每執行一條會更改Redis中的數據的命令,Redis就會將該命令寫入硬盤中的AOF文件。AOF文件的保存位置和RDB文件的位置相同,都是通過dir參數設置的,默認的文件名是appendonly.aof。  
  在Redis的配置文件中存在三種不同的 AOF 持久化方式,它們分別是:
appendfsync always #每次有數據修改發生時都會寫入AOF文件,這樣會嚴重降低Redis的速度
appendfsync everysec #每秒鐘同步一次,顯示地將多個寫命令同步到硬盤
appendfsync no #讓操作系統決定何時進行同步
  爲了兼顧數據和寫入性能,用戶可以考慮 appendfsync everysec選項 ,讓Redis每秒同步一次AOF文件,Redis性能幾乎沒受到任何影響。而且這樣即使出現系統崩潰,用戶最多隻會丟失一秒之內產生的數據。當硬盤忙於執行寫入操作的時候,Redis還會優雅的放慢自己的速度以便適應硬盤的最大寫入速度。

  Redis 4.0 對於持久化機制的優化

  Redis 4.0 開始支持 RDB 和 AOF 的混合持久化(默認關閉,可以通過配置項 aof-use-rdb-preamble 開啓)。  
  如果把混合持久化打開,AOF 重寫的時候就直接把 RDB 的內容寫到 AOF 文件開頭。這樣做的好處是可以結合 RDB 和 AOF 的優點, 快速加載同時避免丟失過多的數據。當然缺點也是有的, AOF 裏面的 RDB 部分是壓縮格式不再是 AOF 格式,可讀性較差。

  補充內容:AOF 重寫

  AOF重寫可以產生一個新的AOF文件,這個新的AOF文件和原有的AOF文件所保存的數據庫狀態一樣,但體積更小。
  AOF重寫是一個有歧義的名字,該功能是通過讀取數據庫中的鍵值對來實現的,程序無須對現有AOF文件進行任何讀入、分析或者寫入操作。  
  在執行 BGREWRITEAOF 命令時,Redis 服務器會維護一個 AOF 重寫緩衝區,該緩衝區會在子進程創建新AOF文件期間,記錄服務器執行的所有寫命令。當子進程完成創建新AOF文件的工作之後,服務器會將重寫緩衝區中的所有內容追加到新AOF文件的末尾,使得新舊兩個AOF文件所保存的數據庫狀態一致。最後,服務器用新的AOF文件替換舊的AOF文件,以此來完成AOF文件重寫操作

redis 事務

  Redis 通過 MULTI、EXEC、WATCH 等命令來實現事務(transaction)功能。事務提供了一種將多個命令請求打包,然後一次性、按順序地執行多個命令的機制,並且在事務執行期間,服務器不會中斷事務而改去執行其他客戶端的命令請求,它會將事務中的所有命令都執行完畢,然後纔去處理其他客戶端的命令請求。  
  在傳統的關係式數據庫中,常常用 ACID 性質來檢驗事務功能的可靠性和安全性。在 Redis 中,事務總是具有原子性(Atomicity)、一致性(Consistency)和隔離性(Isolation),並且當 Redis 運行在某種特定的持久化模式下時,事務也具有持久性(Durability)。
  注意:redis同一個事務中如果有一條命令執行失敗,其後的命令仍然會被執行,沒有回滾。

緩存雪崩和緩存穿透問題解決方案

  緩存雪崩  
  簡介:緩存同一時間大面積的失效,所以,後面的請求都會落到數據庫上,造成數據庫短時間內承受大量請求而崩掉。  
  解決辦法:  
  •   事前:儘量保證整個 redis 集羣的高可用性,發現機器宕機儘快補上。選擇合適的內存淘汰策略。
  •   事中:本地ehcache緩存 + hystrix限流&降級,避免MySQL崩掉
  •   事後:利用 redis 持久化機制保存的數據儘快恢復緩存
 
緩存穿透  
  簡介:一般是黑客故意去請求緩存中不存在的數據,導致所有的請求都落到數據庫上,造成數據庫短時間內承受大量請求而崩掉。  
  解決辦法:
  有很多種方法可以有效地解決緩存穿透問題,最常見的則是採用布隆過濾器,將所有可能存在的數據哈希到一個足夠大的bitmap中,一個一定不存在的數據會被 這個bitmap攔截掉,從而避免了對底層存儲系統的查詢壓力。另外也有一個更爲簡單粗暴的方法(我們採用的就是這種),如果一個查詢返回的數據爲空(不管是數 據不存在,還是系統故障),我們仍然把這個空結果進行緩存,但它的過期時間會很短,最長不超過五分鐘。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章