天天看點

redis核心機制深入解析

Redis Cluster 故障轉移 怎麼保證資料一緻性   

Redis主要涉及的概念包括下列幾大類:

Redis 基本資料結構詳解

Redis 高并發問題政策

Redis 叢集結構以及設計理念

Redis 持久化機制

Redis 應用場景設計

相關的具體要點如下:

什麼是 Redis?

  Redis的靈活性允許各種不同的鍵構造和存儲方案。Red is 性能和可維護性的優劣取決于Redis 資料庫鍵的設計與構造。一種良好而又通用的實踐是在設計Redis 鍵時至少起草一份粗略概要,用于描述存人Redis 中的資訊及采用何種Redis 結構中的初步想法。

為什麼 Redis 需要把所有資料放到記憶體中?

Redis 适用場景有哪些?

Redis常用的業務場景有哪些?

  更加豐富的資料結構。Memcached是多線程伺服器。

  get,set(Redis 2.6.12開始一個指令支援設定分布式鎖),del,append,expire,expireat,ttl,object,debug object,incr,decr,eval

  lrange,lpop,rpush,還有支援阻塞式pop的指令blpop、在清單間移動元素的指令

  keys,需要注意keys會阻塞,不能線上上使用,可以使用scan,它慢一點,是異步的,不會影響阻塞,但是不會去重、需要用戶端去重,使用更複雜。

  sadd,srem,sismember,smembers,還支援集合操作如sinter,sunion,sdiff,交集、并集、差集,跟java Set一樣。

  hset,hget,hgetall,hdel,hincrby

  zadd,zrem,zrange(傳回排名在a-b之間的成員),zrangebyscore(延時隊列),zincrby,以及各種降序、升序,根據排名、分值的指令,應該來說相當實用,可以用于投票、top時間戳等等。

  subscribe, unsubscribe,psubscribe,punsubscribe

  watch,setnx(2.6.12之後就不需要了)

  是。

  因為資料全部在記憶體中,且使用NIO模型。redis利用隊列技術将并發通路變為串行通路,消除了傳統資料庫串行控制的開銷,也避免了不必要的上下文切換和競争條件。

一個字元串類型的值能存儲最大容量是多少?512M。Redis各個資料類型最大存儲量分别是多少?

Redis 持久化機制有哪些? 差別是什麼?

  緩存穿透是指查詢一個一不存在的資料。例如:從緩存redis沒有命中,需要從mysql資料庫查詢,查不到資料則不寫入緩存,這将導緻這個不存在的資料每次請求都要到資料庫去查詢,造成緩存穿透。

  解決方法:如果查詢資料庫也為空,直接設定一個預設值存放到緩存,這樣第二次到緩沖中擷取就有值了,而不會繼續通路資料庫。設定一個過期時間或者當有值的時候将緩存中的值替換掉即可。

  穿透指的是一個不存在key導緻的大面積同時通路DB,擊穿則指的是一個存在的key失效。

  解決方法:1、加分布式鎖機制。2、全局維護ID集合。

  緩存雪崩是指資料未加載到緩存中,或者緩存同一時間大面積的失效,進而導緻所有請求都去查資料庫,導緻資料庫CPU和記憶體負載過高,甚至當機。

  解決方法:1、叢集部署,可以使用Redis Cluster。2、降級(非核心服務下線)、二級緩存。3、Redis備份和快速預熱。

緩存的更新政策有幾種?分别有什麼注意事項?

什麼是分布式鎖?有什麼作用?

分布式鎖可以通過什麼來實作?

  

介紹一下分布式鎖實作需要注意的事項?

Redis怎麼實作分布式鎖?

  先拿setnx來争搶鎖,搶到之後,再用expire給鎖加一個過期時間防止鎖忘記了釋放。**如果在setnx之後執行expire之前程序意外crash或者要重新開機維護了,那會怎麼樣?**set指令有非常複雜的參數,這個應該是可以同時把setnx和expire合成一條指令來用的!也就是lua腳本。

常見的淘汰算法有哪些?

  https://redis.io/topics/lru-cache

  Redis 預設每秒進行10 次過期掃描,為了保證過期掃描不會出現循環過度,導緻結程卡死的現象,算法還增加了掃描時間的上限,預設不會超過25ms 。當用戶端請求到來時,伺服器如果正好進入過期掃描狀态,用戶端的請求将會等待至少25ms 後才會進行處理,如果用戶端将逾時時間設定得比較短,比如10ms ,那麼就會出現大量的連結因為逾時而關閉,業務端就會出現很多異常。是以業務開發人員一定要注意過期時間,如果有大批量的key 過期,要給過期時間設定一個随機範圍,而不能全部在同一時間過期。

  RDB和AOF,redis 4.x開始引入了混合模式(和oracle的rman備份一樣,記錄備份期間的redo,然後恢複時先恢複快照,然後應用redo實作快速恢複),最大化降低恢複時間。

  如果redis執行個體很大,例如幾十GB,那麼使用bgsave建立子程序和儲存快照的時間可能會很長,在虛拟化環境或非SSD環境中,甚至可能高達一二十分鐘。是以對于大型執行個體來說,恰當的評估save的設定是非常重要的。如果可以容忍部分資料丢失,最好是在slave節點執行快照動作。

redis核心機制深入解析

http://www.mamicode.com/info-detail-2329676.html 

  RDB是記憶體資料的二進制序列化形式,在存儲上非常緊湊,Redis 使用作業系統的多程序COW (Copy On Write )機制來實作快照持久化,比較耗資源,是以它并不是完整的,會丢失不少資料的修改,是以結果可能是錯誤的,相比缺少而言、結果錯誤很可能是緻命的。

  AOF 日志記錄的是記憶體資料修改的指令記錄文本。Redis 在長期運作的過程中, AOF 的日志會越來越長。如果執行個體當機重新開機,重放整個AOF 曰志會非常耗時,導緻Redis 長時間無法對外提供服務,是以需要對AOF進行瘦身。Red is 提供了bgrewriteaof 指令用于對AOF 曰志進行瘦身,其原理就是開辟一個子程序對記憶體進行周遊,轉換成一系列Red is 的操作指令,序列化到一個新的AOF曰志檔案中。序列化完畢後再将操作期間發生的增量AOF 日志追加到這個新的AOF日志檔案中,追加完畢後就立即替代舊的AOF 曰志檔案了,瘦身工作就完成了。即使如此,仍然可能很大。

  AOF和資料庫的redo一樣,提供了緩存重新整理模式,是以不同的值會存在丢資料的風險。

  RESP。簡單。

請介紹一下 Redis 的資料類型 SortedSet(zset) 以及底層實作機制?Redis 叢集最大節點個數是多少?

  多級ziplist結構,成B*結構。

redis核心機制深入解析

,運作中加入的時候,這是需要注意的,否則會導緻用戶端無響應,redis 4.x進行了優化,直接socket發送(如果從節點重新開機本地就有rdb,怎麼樣?)。

  redis不支援MM複制(mysql的galera cluster支援)。

  Redis Cluster 可以為每個主節點設定若幹個從節點,當主節點發生故障時,叢集會自動将其中某個從節點提升為主節點。如果某個主節點沒有從節點,那麼當它發生故障時,叢集将完全處于不可用狀态。不過Redis 也提供了一個參數clusterrequire-full-coverage 可以允許部分節點發生故障,其他節點還可以繼續提供對外通路。除此之外,Redis Cluster 提供了一種選項cluster-node-timeout , 表示當某個節點持續timeout 的時間失聯時,才可以認定該節點出現故障,需要進行主從切換。如果沒有這個選項,網絡抖動會導緻主從頻繁切換(資料的重新複制)。

  redis叢集主從切換的相關原理以及案例

redis核心機制深入解析
redis核心機制深入解析

Redis 如何做記憶體優化?

redis核心機制深入解析

  Redis 事務在形式上看起來也差不多,指令分别是multi、exec、discard。multi訓示事務的開始, exec 訓示事務的執行, discard 訓示事務的丢棄。

  隻是一種串行化執行機制,并非ACID所定義的事務。

  Redis 的事務根本不具備“原子性” ,而僅僅是滿足了事務的“隔離性”中的串行化-一目前執行的事務有着不被其他事務打斷的權利。事務在遇到指令執行失敗後,後面的指令還會繼續執行。

  Redis Cluster是去中心化的,每個節點負責整個叢集的一部分資料,每個節點負責的資料多少可能不一樣。這些節點互相連接配接組成一個對等的叢集,它們之間通過一種特殊的二進制協定互動叢集資訊。如下:

redis核心機制深入解析

   為了保證高可用性,每個節點本身通常又部署成m-s模式,是以一共有6節點,如下:

redis核心機制深入解析

  當Redis Cluster 的用戶端來連接配接叢集時,也會得到一份叢集的槽位配置資訊。這樣當用戶端要查找某個key 時,可以直接定位到目标節點(即:用戶端路由方式Twemproxy則是中間件路由,中間件架構最成功的模式,沒落是社群更新不及時)。這種模式不同于經過代理查找目标服務節點,直接在用戶端完成了,避免了單點失敗。Re di s Clu s ter 預設會對key 值使用crcl 6 算法進行hash ,得到-個整數值,然後用這個整數值對16 384 進行取模來得到具體槽位。Redis Cluster 還允許使用者強制把某個key 挂在特定槽位上。通過在key 字元串裡面嵌入tag 标記, 這就可以強制key 所挂的槽位等于tag 所在的槽位。

  參見redis安裝與介紹。

  當我們使用用戶端對Redis 進行一次操作時,用戶端将請求傳送給伺服器,伺服器處理完畢後,再将晌應回複給用戶端。這要花費一個網絡資料包來回的時間。如果連續執行多條指令,那就會花費多個網絡資料包來固的時間。通過管道可以将網絡互動次數從N降低為1。進而大幅度提升性能,在redis沒有到100%之前,增加每個管道中的指令數可以持續提升redis的tps。最典型的就是如緩存了id->userInfo,name->id,此時就可以網絡次數從,2降低為1,一次性儲存一個使用者的資訊。但是可以根據傳回值執行查找嗎?

請說明一下 Redis 的批量指令與 Pipeline 有什麼不同?

  兩者都是為了提升性能。批量指令如mget,hmget常用于針對相同的資料結構執行多個指令,且僅僅發送了一次網絡請求。pipeline則支援異步發送模式,請求、應答數不會減少(這和上面的描述不一緻啊??);預設情況下(即pipeline的參數為true),這就是事務中多個指令一次性執行的實作方式。

  參見redis安裝與介紹。注:redis的慢查詢指的是邏輯處理過程慢,不包含等待時間。

Redis 的慢查詢修複經驗有哪些? 怎麼修複的?

  fanout模式的mq,不通過lpop/lpush分區模式,它支援一條消息發送給所有的訂閱者。必須先啟動消費者,然後再執行生産者。因為Pub Sub 的生産者傳遞過來一個消患, Redis 會直接找到相應的消費者傳遞過去。如果一個消費者都沒有,那麼消息會被直接丢棄。如果開始有三個消費者, 個消費者突然挂掉了,生産者會繼續發送消息,另外兩個消費者可以持續收到消息,但是當挂掉的消費者重新連上的時候,在斷連期間生産者發送的消息,對于這個消費者來說就是徹底丢失了。還要注意用戶端緩存超出導緻丢資料。

  如果Redis 停機重新開機, PubSub 的消息是不會持久化的,畢竟Redis 看機就相當于一個消費者都沒有,所有的消息會被直接丢棄。正是因為Pub Sub 有這些缺點,在消息隊列的領域它幾乎找不到合适的應用場景。redis 5.0引入了新的Stream(借鑒了kafka的設計思想)資料類型,支援消息的持久化。

  一些特殊的全key掃描,如keys a*

怎麼去發現 Redis 阻塞異常情況?

  在redis 4.x中,增加了memory指令,極大地簡化了大對象的查找。參見:

  Redis 提供了配置參數maxmemory來限制記憶體超出期望大小。

  當實際記憶體超出maxmemory時, Redis 提供了幾種可選政策( maxmemory-policy)來讓使用者自己決定該如何騰出新的空間以繼續提供讀寫服務。

  1. noeviction :不會繼續服務寫請求( del 請求可以繼續服務),讀請求可以繼續進行。這樣可以保證不會丢失資料,但是會讓線上的業務不能持續進行。這是預設的淘汰政策。

2. volatile-lru : 嘗試淘汰設定了過期時間的key,最少使用的key 優先被淘汰。沒有設定過期時間的k巳y 不會被淘汰,這樣可以保證需要持久化的資料不會突然丢失。

3 . volatile-ttl :跟上面幾乎一樣,不過淘汰的政策不是LRU ,而是比較key 的剩餘壽命時的值,憂l 越小越優先被淘汰。

4. volatile-random :跟上面幾乎一樣,不過淘汰的key 是過期key 集合中随機的key 。

5. allkeys-lru :差別于volatile-lru ,這個政策要淘汰的key 對象是全體的key 集合,而不隻是過期的key 集合。這意昧着-些沒有設定過期時間的key 也會被淘汰。

6. allkeys-random :跟上面幾乎一樣,不過淘汰的key 是随機的key 。

什麼是 bigkey? 有什麼影響?

怎麼發現bigkey?

冷熱資料表示什麼意思?

緩存命中率表示什麼?

怎麼提高緩存命中率?

如何優化 Redis 服務的性能?

如何實作本地緩存?請描述一下你知道的方式

請介紹一下 Spring 注解緩存

  有幾個參數可以控制其行為。

  aof-load-truncated yes:如果AOF檔案結尾損壞,Redis啟動時是否仍載入AOF檔案

  從節點不會進行過期掃描,從節點對過期的處理是被動的。主節點在key 到期時,會在AOF 檔案裡增加一條del 指令,同步到所有的從節點,從節點通過執行這條del 指令來删除過期的key 。因為指令同步是異步進行的,是以如果主節點過期的key 的del 指令沒有及時同步到從節點的話,就會出現主從資料的不-緻,主節點沒有的資料在從節點裡還存在,比如上一節的叢集環境分布式鎖的算法漏洞就是因為這個同步延遲産生的。

Redis sentinel (哨兵) 模式優缺點有哪些?

  在複制的基礎上,哨兵實作了自動化的故障恢複。缺陷:寫操作無法負載均衡;存儲能力受到單機的限制。

Redis 叢集架構模式有哪幾種?

如何設定 Redis 的最大連接配接數?檢視Redis的最大連接配接數?檢視Redis的目前連接配接數?

Redis 的連結清單資料結構的特征有哪些?

請介紹一下 Redis 的 String 類型底層實作?

Redis 的 String 類型使用 SSD 方式實作的好處?

設計一下在交易網站首頁展示當天最熱門售賣商品的前五十名商品清單?

spring redis讀寫分離配置

redis與資料庫的雙寫一緻性

  先讀緩存,後讀資料庫。先寫資料庫,後寫緩存(懶寫模式)。

參考:《Redis 深度曆險:核心原理與應用實踐》、《Redis實戰》、吐血整理60個Redis面試題、redis面試常見的10個問題,跳表可參考:https://zhuanlan.zhihu.com/p/92536201、

redis開發最佳實踐:最主要是1、節省記憶體;2、減少網絡互動;3、注意單次操作大小控制,避免redis單線程pending。

redis 大value的問題,參考https://www.v2ex.com/t/353568,https://www.lmlphp.com/user/418/article/item/30305/(主要是hash取模,找個好的算法,和并行一個道理)。實際上我們在SSD上測試下來,從開始,value的增大對于set而言線性下降,從接近10K開始,get影響不大。

 https://redis.io/topics/benchmarks

花若盛開,蝶自飛來,你若精彩,幸福開懷!2020年12月11日-18日

繼續閱讀