JAVA面試——分布式緩存


    • 為什么用緩存?
      • 高性能:減少查詢同一個數據時的響應速度
      • 高並發:減少數據庫的承載壓力(2000/s),緩存走內存,天然支撐高並發
    • 緩存的不良后果:
      • 緩存與數據庫的雙寫不一致
      • 緩存雪崩
      • 緩存穿透
      • 緩存並發競爭
    • Redis和memcached區別(單線程、NIO、異步)
      • Redis支持服務器端數據操作:數據類型更多,功能更全
      • 內存使用效率對比:簡單key-value時memcached效率高,hash結構存儲Redis高
      • 性能對比:Redis單線程,小數據時Redis高;大數據時多線程的memcached高
      • 集群模式:memcached不支持集群,Redis支持
    • Redis單線程模型:
      • 文件事件處理器,單線程,通過IO多路復用程序同時監聽多個socket,通過socket上的事件選擇對應的事件處理器處理事件
      • AE_READABLE:socket可讀(連接操作、客戶端對Redis執行write操作,close操作)
      • AE_WRITABLE:socket可寫(客戶端對Redis執行read操作)
    • Redis單線程模型為什么效率高?
      • 純內存操作(事件處理器在內存操作,性能高1ms)
      • 核心基於非阻塞IO多路復用機制(不處理、直接壓隊列)
      • 單線程避免了多線程的頻繁上下文切換問題
    • Redis有哪些數據類型?
      • string
      • hash
        • 結構化數據,存放對象
          • key=150
          • value={
          •   “id”: 150,
          •   “name”: “zhangsan”,
          •   “age”: 20
          • }
      • list
        • 列表性數據結構(微博粉絲)
          • key=某大v
          • value=[zhangsan, lisi, wangwu]
      • set
        • 無需集合,自動去重
      • sorted set
        • 去重&排序
    • Redis的過期策略、內存淘汰機制
      • 定期刪除+惰性刪除
        • 每隔100ms抽取設置過期時間的key,檢查是否過期后刪除(定期)
        • 獲取某個key時,redis檢查是否過期(惰性)
      • 內存淘汰
1)noeviction:當內存不足以容納新寫入數據時,新寫入操作會報錯,這個一般沒人用吧,實在是太惡心了
2)allkeys-lru:當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的key(這個是最常用的)
3)allkeys-random:當內存不足以容納新寫入數據時,在鍵空間中,隨機移除某個key,這個一般沒人用吧,為啥要隨機,肯定是把最近最少使用的key給干掉啊
4)volatile-lru:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,移除最近最少使用的key(這個一般不太合適)
5)volatile-random:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,隨機移除某個key
6)volatile-ttl:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,有更早過期時間的key優先移除
    • 手寫LRU算法
  • Redis高並發、高可用、緩存一致性:
    • Redis高並發:主從架構,一主多從,單主用來寫入數據,單機幾萬QPS,多從用來查詢數據,多個從實例可以提供每秒10W的QPS。如果需要緩存容納數據量大,用Redis集群。
    • Redis高可用:如果你做主從架構部署,其實就是加上哨兵就可以了,就可以實現,任何一個實例宕機,自動會進行主備切換。
    • 高並發
      • 主從架構,實現讀寫分離(master寫,slave讀),水平擴容
      • redis replication->主從架構->讀寫分離->水平擴容支撐讀高並發
      • master開啟持久化
      • 主從架構核心原理:
        • master啟動線程,生成RDB快照,發送給slave
        • 斷點續傳,記錄offset繼續復制
        • 無磁盤復制:在內存創建rdb,發送給slave
    • Redis replication(復制)的完整流程
    • 數據同步的核心機制:
      • master和slave都會維護一個offset
      • backlog:用來全量復制中斷后的增量復制
      • master run id:區分master(重啟或者數據發生變化)
      • psync:psync runid offset,從節點使用此命令從master node進行復制
    • 全量復制
      • master生成快照
      • 發送給slave node
      • master在生成快照時,將所有新的寫命令緩存在內存中,slave保存rdb后,將新的寫命令復制
      • slave在接收到rdb后,清空舊數據,加載rdb
      • 如slave開啟aof,立即重寫aof
    • 增量復制
      • 全量復制中斷
      • master用runid和offset從backlog中獲取到丟失數據,發送給slave
    • heartbeat
      • master默認每隔10秒發送一次heartbeat,salve node每隔1秒發送一個heartbeat
    • 異步復制
      • master每次接收到寫命令之后,現在內部寫入數據,然后異步發送給slave node
    • 高可用性
      • 基於哨兵(sentinal)的高可用,故障轉移(failover),主備切換
    • 哨兵:
      • 哨兵的作用:
      1. 集群監控,負責監控redis master和slave進程是否正常工作
      2. 消息通知,如果某個redis實例有故障,那么哨兵負責發送消息作為報警通知給管理員
      3. 故障轉移,如果master node掛掉了,會自動轉移到slave node上
      4. 配置中心,如果故障轉移發生了,通知client客戶端新的master地址
      • 分布式,哨兵集群運行
    • 主備切換數據丟失問題:
      • 異步復制導致:
        • master->slave復制是異步的,可能沒復制完,master宕機
      • 集群腦裂導致:
        • master主節點,出現異常性的相同工作的兩個節點
        • client可以和舊master寫數據,恢復后舊master成為slave后數據丟失
      • 解決:
        • min-slaves-to-write 1
        • min-slaves-max-lag 10
        • 要求至少有1個slave,數據復制和同步的延遲不能超過10秒
        • 如果說一旦所有的slave,數據復制和同步的延遲都超過了10秒鍾,那么這個時候,master就不會再接收任何請求了
    • 哨兵的核心原理:
      • sdown和odown轉換:
        • sdown主觀宕機
        • odown客觀宕機
        • quorum指定數量
      • 哨兵的自動發現機制:
        • __sentinel__:hello這個channel里發送一個消息
      • slave配置的自動糾正
      • slave->master選舉算法
        • 跟master斷開連接的時長
        • slave優先級
        • 復制offset
        • run id
  • Redis重啟數據恢復(數據持久化)
    • 持久化的意義:數據備份、故障恢復
    • 兩種持久化:RDB、AOF
      • RDB:對Redis中數據執行周期性的持久化
      • AOF:對於每條寫入命令作為日志,以append-only模式寫入一個日志文件中(更加完整)
      • Redis重啟后,通過回放AOF日志中的指令重新構建數據集
      • AOF大到一等程度后,rewrite操作,構建更小的AOF文件
    • RDB優劣勢:
      • 優點:(冷備)
        • 生成多個數據文件,適合冷備。AOF需要寫腳本處理。
        • RDB對Redis性能影響小,fork子進行進行RDB持久化
        • RDB重啟恢復速度快
      • 缺點:
        • 恢復效果差,數據丟失
        • fork子進程時,數據文件特別大,會對客戶端服務暫停數毫秒
    • AOF優劣勢:
      • 優點:
        • 保護數據不丟失
        • append-only寫入,沒有磁盤尋址開銷,寫入性能高,文件不易損壞
        • AOF日志文件過大rewrite對客戶端讀寫性能影響小
        • 日志文件可讀
      • 缺點:
        • 日志文件大
        • 支持的寫QPS低
        • 健壯性低
    • 結合RDB和AOF同時使用
  • Redis集群模式
    • 分布式數據的核心算法,數據分布的算法:
      • redis cluster——hash slot算法
        • 每個master持有部分slot
    • 節點間的內部通信機制
      • 集群的元數據維護:集中式(ZooKeeper)、gossip
        • gossip協議:元數據分散,降低壓力,更新有延遲(meet ping pong fail)
      • 10000端口:用於節點間通信,為服務接口+10000,ping->pong
      • 交換信息的內容:故障信息、節點的增刪、hash slot信息。。。
    • jedis: Redis的java client客戶端
      • smart jedis:本地維護hashslot->node的映射表,緩存,不需要節點moved重定向
      • hash tag手動指定對應slot,set key1:{100}
    • 高可用與主備切換:
      • pfail(主觀宕機) fail(客觀宕機)
      • 與哨兵類似
  • Redis緩存雪崩與緩存穿透
    • 緩存雪崩:
      • 事前:Redis高可用(主從+哨兵、Redis Cluster)
      • 事中:本地ehcache緩存(系統內部小緩存)+hystrix限流(限流降級組件)
      • 事后:Redis持久化,快速恢復緩存數據
    • 緩存穿透:
      • 沒查到,寫空值到緩存中(set -999 UNKNOWN)
      • 使用布隆過濾器或者壓縮filter提前攔截
  • 緩存與數據庫雙寫數據一致性(讀寫串行化):
    • 緩存+數據庫讀寫模式:cache aside pattern
      • 讀。先緩存,再數據庫,讀完放入緩存
      • 更新,先刪除緩存(緩存復雜計算得到、不會頻繁訪問),再更新數據庫
    • 簡單場景:先刪緩存,在修改數據庫
    • 復雜場景(刪除緩存,修改數據庫之前,讀后緩存舊數據,數據庫新修改)
      • 數據庫與緩存更新讀取操作進行異步(線程)串行化
        • 內存隊列放請求,一個隊列對應一個線程,串行進行操作
      • 讀請求長時阻塞
        • 隊列里寫請求過多(部署多個服務,分攤數據更新)
        • 加多機器,每個機器上部署的服務實例處理更少的數據
      • 多服務實例部署的請求路由
        • 同一個商品的讀寫請求,路由到同一台機器上
        • nginx,hash路由功能
      • 熱點商品的路由問題(讀寫請求高)
        • 商品更新清空緩存,導致讀寫並發,更新頻率不高影響不大
  • Redis並發競爭問題:
    • 多客戶端並發寫一個key
    • CAS類的樂觀鎖方案
    • zookeeper提供分布式鎖
    • 每個value的時間戳要比緩存中的時間戳更新,才可以寫
  • 生產環境中的Redis怎么部署


免責聲明!

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



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