Database & Cache

系統設計一定會碰到 database 的問題,一個產品必定會碰到 database 的開發。因為當我們想要儲存資料時,是將資料結構化後儲存到資料庫,再由資料庫儲存到文件系統,資料庫幫我們經手與文件系統打交道這件事。

面試時,一個問題下來:「如何設計使用者系統?」

這時我們應該要用 4S 分析,分別是 Scenario, Service, Storage, Scale

  • Scenario: 場景分析,與面試官聊天,了解需求,並順便導出 QPS 等等
  • Service: 功能需要拆分成哪幾個 Service? 像是 AuthService, UserInfoService, FriendShipService 等等
  • Storage: 根據 QPS 而選用哪種資料庫? 資料的 Schema 是? ER relation 等等
  • Scale: 你要如何 scale?

QPS: query per second, 大致上需估算 average, peak 的 QPS,然後根據結果挑選 DB

  • MySQL / PostgreSQL : 約 100 ~ 1000 QPS
  • MongoDB / Cassandra : 約 10k QPS
  • Memcached / Redis : 約 100k ~ 1M QPS

SQL 類的資料庫支援複雜的語句,所以速度較慢; NoSQL 則僅支援簡單的語句,所以速度較快,而且通常支援 scaling


Service 設計時,盡量簡單而不要 over design

如果 service 為讀多寫少 => 必用 cahce 優化; 反之則用 NoSQL 快速寫入


*** 練習 LRU Cache!!!!!!!

Cache 是一種概念,將「常用到的資料」儲存在某個地方(不是資料庫),下次要取用時可以快速取得

常見的有

  • Memcached: 不支持持久化,關掉資料就消失
  • Redis: 支持持久,也支持 conurrency, it is consistent ()

Cache 有分成 cache-through, cache-aside 類型,主要分別是 cache 是與 DB 直接溝通嗎? 如果是就是 cache-through 類型

Cache 並不是資料庫,而是一種「優化」

使用 Cache 時要記住,DB、cache 並不總是一致,不能假設所有操作都會成功,DB 操作的一個要點是要保持一致性

以下為較正確的寫法:

def setUser(key, value):
    ...
    cache.delete(key)
    database.set(key, value)

其餘的順序都會導致 db, cache 不一致,例如

    database.set(key, value)  -> 這行做完失敗的話,資料會不一致
    cache.set(key, value)

用到期時間可以有效的降低不一致性


假設要設計 FriendShip Service,先詢問要有那些功能,EX: 好友查詢

好友查詢又可以想到說好友關係是雙向還是單向? 根據關係可以去想出資料庫的表應該怎麼做,資料庫怎麼挑等等

挑選 SQL 或 NoSQL

  • 大部分情況下都可以
  • 需要 Transaction 的不能用 NoSQL (NoSQL 不能確保一致)
  • 想要複雜功能則用 SQL
  • 是否需要 Sequential ID? 要則選 SQL
  • 更高性能選用 NoSQL

萬年問題: How to scale?

除了 QPS,其他的 concern 為 single point failure, DB scaling

scale 可以從 load balance 和資料庫下手,

資料庫的話可以做 sharding, Replica 等等

sharding 又分為

  • vertical sharding : 某些表存到某台機器,或是某些 column 存到某台機器,可以把較常 query 的擺一起,cache hit 會上升,但是缺點也很明顯,就是如果表的 row 很多還是沒用啊!
  • horizontal sharding : 將 row 拆分到其他機器,暴力法為將 id % n,可是要遷移時會是很大的問題

results matching ""

    No results matching ""