iT邦幫忙

2024 iThome 鐵人賽

DAY 29
0
Software Development

埋藏在後端工程下的地雷與寶藏系列 第 29

Day-29 | Database - 什麼時候要使用 Redis ?

  • 分享至 

  • xImage
  •  

倒數兩天,來聊聊最近常使用的 Redis 和傳統資料庫的差別 ~

What is Redis

Redis can be used as a database, cache, streaming engine, message broker, and more.
https://ithelp.ithome.com.tw/upload/images/20241013/201509270G2EmKoM4X.png
Redis(Remote Dictionary Server) 是一個開源的高效能、基於主記憶體的 NoSQL 資料庫。他透過 key-value 的方式來做資料的存放,並支援多種資料結構,如 stringhashlistset 等。因為它的高效能,常被使用在快取 (cache)。

Redis v.s. 傳統的資料庫

一般來說,我們開發時都會需要儲存資料,最常見的就是 Database,如: MySQL、Postgresql 等。但當我們遇到需要頻繁讀寫某些資料時,可以使用快取 (cache) 來提升我們的存取的速度。在這樣的情境下,因為資料存放在記憶體的特性,相較於存放在硬碟中的資料庫是更好的選擇。

  1. 儲存在記憶體 vs. 儲存在硬碟

    • Redis:是一個儲存在記憶體的資料庫。因為記憶體的存取速度比硬碟快很多(通常是幾百倍), Redis 能夠較快地進行讀寫操作。當然 Redis 也支援持久化,但它的設計目標是高效能的存取,因此大多數操作都發生在記憶體中。
    • 傳統資料庫(如 MySQL、PostgreSQL):資料庫大多數資料是儲存在硬碟上。雖然資料庫會有一些機制來進行記憶體快取(如 PostgreSQL 的 shared_buffers),但當資料超出快取容量或有複雜的查詢時,資料庫還是需要從硬碟中讀取資料。硬碟的存取速度比記憶體慢,因此快取存在資料庫中通常效能較存在記憶體來的低。
  2. 簡單的資料結構 vs. 複雜的查詢處理&Index

    • Redis:使用的是簡單且高效的 key-value,並且不涉及複雜的查詢分析等步驟,因此執行速度可以比較快。
    • 傳統資料庫:資料庫可能需要處理複雜的查詢,像是我們前面有談到的 Postgresql 的 scan path 優化或 join strategies。即使在簡單的查詢下,資料庫還需要分析如何選擇最佳策略,這些額外的分析步驟會導致比 Redis 還慢,更不用說複雜的 JOIN、GROUP BY 等操作了。

持久化

雖然 Redis 儲存在記憶體中,重新開機資料就不見了,但它還是有讓資料永久保存的機制。

  • RDB (Redis Database Backup):在指定時間點生成快照,以非同步方式從主記憶體以RDB格式寫入硬碟。
  • AOF (Append Only File):1.1版本開始使用更安全的AOF格式替代,一種只能追加的紀錄檔類型。將資料修改操作記錄起來。Redis能夠在後端對只可追加的記錄進行修改,從而避免紀錄檔的無限增長。

Pub/Sub

Redis 原生就支援如之前 Message Queue 的 Pub/Sub 方式來傳遞訊息,但它限制較多。

  • Pub/Sub 的內容,不會用鍵值的方式去保存,導致訊息沒收到 -> 資料遺失
  • buffer size 較小,若訊息量過大,舊的資料會直接被丟棄
  • 不支援多個 consumer groups

這一系列的問題導致 Redis Pub/Sub 不會被使用來做 Message Queue,而是透過 Pub/Sub 執行再一些需要即時廣播的情境,直到 5.0 的 Redis Streams 出現。

Redis Streams

是在 Redis 5.0 中新增的功能,實現了一個正常的 Message Queue。

  • 持久化
    • 與 Pub/Sub 不同,Redis Streams 讓訊息可以持久化保存,即使 Consumer 暫時無法接收訊息,訊息仍然會保存在 Redis 中,直到被處理或達到指定的保留時間。
  • 訊息編號
    每條訊息都會分配一個唯一的 ID,通常是時間戳加上序列號,可以精確地找到訊息。
  • Consumer group
    • Redis Streams 支援多個 Consumer,這允許多個 Consumer 同時從同一個 Stream 中處理訊息,而不會重複處理。還可以查詢每個的處理進度,增加處理效率。

簡單 Python 執行範例

import redis

r = redis.Redis(host='localhost', port=6379, db=0)

r.set('user', 'yusin') 
print(r.get('user').decode())  

Reference


上一篇
Day-28 | Python - Decorator 裝飾器
下一篇
Day-30 | 總結&回顧 + 文章目錄
系列文
埋藏在後端工程下的地雷與寶藏30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言