redis核心機制深入解析


redis的安裝與使用介紹,參見redis安裝與介紹

Redis Cluster 故障轉移 怎么保證數據一致性   https://www.oschina.net/question/128542_2307816

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

  • Redis 基本數據結構詳解
  • Redis 高並發問題策略
  • Redis 集群結構以及設計理念
  • Redis 持久化機制
  • Redis 應用場景設計

相關的具體要點如下:

什么是 Redis?

Redis 的特點有哪些?

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


為什么 Redis 需要把所有數據放到內存中?
Redis 適用場景有哪些?
Redis常用的業務場景有哪些?

Memcached 與 Redis 的區別都有哪些?

  更加豐富的數據結構。Memcached是多線程服務器。

Redis常用的命令有哪些?https://redis.io/commands(redis 3/4/5都增加了不少很實用的特性和命令)

  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之后就不需要了)

Redis 是單線程的嗎?

  是。

Redis 為什么設計成單線程的?

  因為數據全部在內存中,且使用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腳本。
常見的淘汰算法有哪些?

Redis 淘汰策略有哪些?

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

Redis 緩存失效/過期策略有哪些?很重要

  Redis 默認每秒進行10 次過期掃描,為了保證過期掃描不會出現循環過度,導致結程卡死的現象,算法還增加了掃描時間的上限,默認不會超過25ms 。當客戶端請求到來時,服務器如果正好進入過期掃描狀態,客戶端的請求將會等待至少25ms 后才會進行處理,如果客戶端將超時時間設置得比較短,比如10ms ,那么就會出現大量的鏈接因為超時而關閉,業務端就會出現很多異常。所以業務開發人員一定要注意過期時間,如果有大批量的key 過期,要給過期時間設置一個隨機范圍,而不能全部在同一時間過期。

Redis 的持久化機制有幾種方式?

  RDB和AOF,redis 4.x開始引入了混合模式(和oracle的rman備份一樣,記錄備份期間的redo,然后恢復時先恢復快照,然后應用redo實現快速恢復),最大化降低恢復時間。相關配置可以參考https://www.cnblogs.com/lxwphp/p/11281066.html

  如果redis實例很大,例如幾十GB,那么使用bgsave創建子進程和保存快照的時間可能會很長,在虛擬化環境或非SSD環境中,甚至可能高達一二十分鍾。因此對於大型實例來說,恰當的評估save的設置是非常重要的。如果可以容忍部分數據丟失,最好是在slave節點執行快照動作。

 

請介紹一下持久化機制 RDB, AOF的優缺點分別是什么?

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

  AOF 日志記錄的是內存數據修改的指令記錄文本。Redis 在長期運行的過程中, AOF 的日志會越來越長。如果實例宕機重啟,重放整個AOF 曰志會非常耗時,導致Redis 長時間無法對外提供服務,所以需要對AOF進行瘦身。Red is 提供了bgrewriteaof 指令用於對AOF 曰志進行瘦身,其原理就是開辟一個子進程對內存進行遍歷,轉換成一系列Red is 的操作指令,序列化到一個新的AOF曰志文件中。序列化完畢后再將操作期間發生的增量AOF 日志追加到這個新的AOF日志文件中,追加完畢后就立即替代舊的AOF 曰志文件了,瘦身工作就完成了。即使如此,仍然可能很大。

  AOF和數據庫的redo一樣,提供了緩存刷新模式,所以不同的值會存在丟數據的風險。

Redis 通訊協議是什么?有什么特點?

  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集群主從切換的相關原理以及案例參見https://www.cnblogs.com/amei0/p/8177076.html,https://blog.csdn.net/Aquester/article/details/85936185

 

Redis 如何做內存優化?

 

Redis 事務相關命令有哪些?

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

Redis 事務的注意點有哪些?

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

Redis 為什么不支持回滾?

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

請介紹一下 Redis 集群實現方案

  Redis Cluster是去中心化的,每個節點負責整個集群的一部分數據,每個節點負責的數據多少可能不一樣。這些節點相互連接組成一個對等的集群,它們之間通過一種特殊的二進制協議交互集群信息。如下:

  

 

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

  

 

  當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安裝與介紹

Redis 集群會有寫操作丟失嗎?為什么?

請介紹一下 Redis 的 Pipeline (管道),以及使用場景

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


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

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

Redis 慢查詢是什么?通過什么配置?

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

Redis 的慢查詢修復經驗有哪些? 怎么修復的?

請介紹一下 Redis的發布訂閱功能

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

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

請介紹幾個可能導致 Redis 阻塞的原因

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

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

如何發現大對象

  在redis 4.x中,增加了memory命令,極大地簡化了大對象的查找。參見:https://blog.csdn.net/yunqishequ1/article/details/78751492

Redis 的內存消耗分類有哪些?內存統計使用什么命令?

  參見https://blog.csdn.net/yunqishequ1/article/details/78751492

簡單介紹一下 Redis 的內存管理方式有哪些?如何設置 Redis 的內存上限?有什么作用?淘汰策略(很重要)

  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 文件的數據出現異常,Redis服務怎么處理?

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

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

Redis 的主從復制模式有什么優缺點?

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


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

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


Redis 集群架構模式有哪幾種?
如何設置 Redis 的最大連接數?查看Redis的最大連接數?查看Redis的當前連接數?
Redis 的鏈表數據結構的特征有哪些?
請介紹一下 Redis 的 String 類型底層實現?
Redis 的 String 類型使用 SSD 方式實現的好處?
設計一下在交易網站首頁展示當天最熱門售賣商品的前五十名商品列表?

spring redis讀寫分離配置

redis與數據庫的雙寫一致性

  先讀緩存,后讀數據庫。先寫數據庫,后寫緩存(懶寫模式)。https://blog.csdn.net/qq_35190492/article/details/103004235

參考:《Redis 深度歷險:核心原理與應用實踐》、《Redis實戰》、吐血整理60個Redis面試題redis面試常見的10個問題,跳表可參考:https://segmentfault.com/a/1190000020596941、https://zhuanlan.zhihu.com/p/92536201、https://www.cnblogs.com/Elliott-Su-Faith-change-our-life/p/7545940.html

redis開發最佳實踐:https://blog.csdn.net/lavorange/article/details/90743392,最主要是1、節省內存;2、減少網絡交互;3、注意單次操作大小控制,避免redis單線程pending。

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

[root@ta5host bin]# ./redis-benchmark -t get,set -n 1000000 -d 10000
====== SET ======
  1000000 requests completed in 13.02 seconds
  50 parallel clients
  10000 bytes payload
  keep alive: 1

100.00% <= 1 milliseconds
100.00% <= 1 milliseconds
76804.91 requests per second

====== GET ======
  1000000 requests completed in 10.56 seconds
  50 parallel clients
  10000 bytes payload
  keep alive: 1

100.00% <= 1 milliseconds
94688.01 requests per second


[root@ta5host bin]# ./redis-benchmark -t get,set -n 1000000 -d 8000
====== SET ======
  1000000 requests completed in 9.30 seconds
  50 parallel clients
  8000 bytes payload
  keep alive: 1

100.00% <= 1 milliseconds
100.00% <= 1 milliseconds
107492.20 requests per second

 https://redis.io/topics/benchmarks


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM