跳至主要内容

Client Side Caching in Redis

本文為此篇 文章 的筆記。

Foreword

本文的 Client Side caching in Redis 為以下架構:

  • 以 Redis 當作主要 Database (不是作為 cache 使用)
  • Client side cache 指的是 Application(Server machine) 的 local memory cache。
  • 本文內的 Client 指的是 Application,Server 指的是 Redis Server(Database)

Introduction

Client side cache 對提升系統效能有很大的幫助。當 Application 發送請求到 Database,並從 Database 拿到某筆資料後便可以把資料存在 Application 內的 Local memory。當下次要發送相同請求時,便可以直接從 Memory 拿取,而省掉與 Database 的溝通時間,以及 Database 跑 Query 的時間。

  • 發送請求至資料庫,並把結果存在 Memory
  • 下次請求時,不必與資料庫溝通!

通常 Cache 會存取 High Read 的資料。其他的特性如 Not frequently change 以及 Computed expensive 也可以考慮。

Problems with above pattern

  • 當資料發生變動時,如何去更新或刪除 Cache 裡的舊資料。

    • 尤其當系統內有多台 Machine 運行時,情況更複雜
  • 可能解法

    1. Simple: Time-to-Live index(TTL)
      • 設定 Cache 資料的過期時間
    2. Complex: 偵測 Database 更新的 Event,當發生變動時通知 Cache 更改
      • 可以使用 Pub/Sub system。發生變動時 Publish message,並傳給所有 Subscribe 此 Event 的 Machine。
      • 缺點:
        • Pub/Sub 通常會送通知給所有 Machine,因為不知道誰有 Cache 資料,誰沒有。
        • 實作複雜
  • Redis 6 支援了 Client-side caching,讓上述 Pattern 可以簡單且有效率的達成

Implementation of Client side caching in Redis

Two modes

  1. Default mode Redis Server(Database) 會記錄每個 Client 有存取過那些 Key,當 key 發生變動時,發送 invalidation 訊息給那些 Clients。
  2. Broadcasting mode 不紀錄誰存了哪些 key,發送通知給所有 Clients
  • Default mode 需先 ENABLE TRACKING

  • Redis Server 如何記錄 client-side caching?

    • Invalidation table(存在 memory)
      • 紀錄各個 Client 的 key 存取紀錄
      • 當 Table 滿了,則把 old key evict,並通知有記錄此 Key 的 client 當作這個 key 已經過期。

Two connections mode

舊的 Protocol 中 (RESP2),Client 會需要使用兩個 Connection 來與 Server 溝通。

  • 其中一個 Client 負責發送 Query
  • 其中一個 Client 負責接收 Invalidation message

新的 Protocol 中 (RESP3) 可以只用一個 connection 就做到 Query 跟接收 Invalidation

  • 但當 Client 主動發送訊息後才會接收到 Invalidation

What tracking tracks?

  • 預設情況下,Client 不需要告訴 Server 他們需要 cache 的 key 有哪些
    • Server 會 cache 所有被讀的 key
  • Tradeoff
    • Cache All key
      • Client server 溝通成本較低
      • Server 會須存取較多資料,且 Client 可能接收到無用的 invalidation 訊息
    • Cache specific key
      • Client server 溝通成本較高

Cache specific key

  • OPTIN
    • Client 主動告訴 Server 該 cache 那些 key
      • 當 Read 前發送 CACHING YES 告訴 server 下個 read 要 cache

NOLOOP option

當目前 Client write 時,自己不會接收到 invalidation message。

Avoid Race condition

當發送 Read 後,在收到回覆前就收到 invalidation message,可能會造成 race condition

  • Invalidate 後的 Response 可能會寫入 cache

  • 解決方法為在發送 Read query 時,同時也在 local 記錄此行為。這樣在後續處理就不會有問題

What to cache

  • 我們想要 cache 的 key 應該要符合:
    • 很常被讀
    • 變動頻率在一個合理的範圍內

Other hints

  • 在 Read server 時也順便紀錄 TTL

Reference: