這一篇是紀錄參加 TGONext - TGONetworks 導師計畫架構一組第三次聚會的旁聽筆記,導師計畫歡迎小組間跨組討論因此自己只要時間允許會參加其他組的討論,參加完後也會整理討論的筆記方便日後回顧,在過去兩個月有參加的架構組筆記分別如下 為了日後讓自己可以更快理解因此整理筆記時有加上自己理解的說明與圖片,其中若是自己有理解不正確的地方是錯誤的部分歡迎各位高手一同討論或給予指導
Database Migration
在這次聚會的一開始同學拋出 Database Migration 的議題,程式碼有版本控制系統,遇到異常狀況時可以找到原本執行正常的程式碼快速進行 Rollback 的動作,那麼資料庫遇到類似狀況要如何 rollback 呢? Ant 請同學分享針對過去的經驗或是解法,可能的解決方案如下
- 不刪除資料及欄位
- 保存刪除資料,使用 Trigger 將資料複製到另一個 Table
- 將要異動的 Table 建立一份 snapshot 快照
- Rename & Copy
導師 : 如果不刪除資料的話,大家覺得會有什麼問題?如果資料庫有很多非必要資料或是欄位時,如果不刪除的話會占用 disk 或是 memory,在傳輸時會多占用網路頻寬;存放過多 Dirty data,後人在維護時也有可能因為不敢亂刪除資料或是欄位,因而繼續存放演變為技術債,也可能會讓 db 的 loading 越來越高,因此可能會影響到資料庫的效能,為了不影響資料庫的效能處理方式有很多種,常見有兩種方式處理
- 將沒用到的放置在另一個 Table,如果之後 Database 需要 Migration 時可以將所需要資料移回來
- 將不需要用到的資料 snapshot,有需要 Rollback 時再將 snapshot 資料回復到原本的資料庫中
RDBMS 是 row base database,新增一個欄位所需要的時間取決於目前資料量的多寡,如果目前異動的 Table 有兩千萬筆 row data 時,這兩千萬筆資料都需要新增 columns,在 Production 的 Table 新增欄位會有 lock 的情況發生,也就是說可能會有 downtime 的狀況產生,在過去的經驗如果要在核心 Table 進行異動或是 index rebuild 的話,會在網站者使用者相對較少的時間進行停機告知用戶網站正在維修中(Under Maintenance),在交易量大的網站中對於 downtime 是格外重視的,在 PostgreSQL 11 與 MySQL 8 分別都有支援新增欄位不會 Table lock 的方法。
那麼不停機要新增欄位,要怎麼做會比較好呢?在 MySQL 有工具可以協助達到此目的 : gh-ost,原理如下 了解運作原理之後,那麼它可能的缺點會是什麼?舉例來說目前資料庫中有些 Table 近 2G 的空間,會進行 COPY Table 資料,可能問題會是 COPY 原有 Table 資料過程中,由於資料量非常龐大此時 Disk IO 會飆高,cpu high或是既有空間會不足的情況發生,這都是使用前需要留意的地方。
Row Based Database vs Column Based Database
在比較 RDBMS 與 NoSQL 的特性時,導師也提到可以從 Row Based Database 與 Column Based Database 的設計進行研究,這方面比較不熟因此列出網路上文章日後有時間
- Rowise vs Columnar Database? Theory and in Practice
- Difference between Row oriented and Column oriented data stores in DBMS
- Column-Based or Row-Based: That is the Question
資料結構 : Tree
接著討論有關 RDBMS 資料庫與 NoSQL 本質上的差異,以及資料庫中的重要觀念 B Tree & B+ Tree,內容相信大家都了解這裡就不在說明,這裡列出幾個自己覺得說明蠻清楚的網站讓大家了解其原理
軟體架構演進
接著回到軟體架構的討論,在上次的討論中有提到 架構的演進,在討論的一開始導師又拋出問題給同學
導師 : 當單機承受不住的時候,為了支持更大的量,你會怎麼做 ?
- 機器硬體加大
- 橫向擴充
- 服務拆分
- Cache Server
- Queue
擴充方式
Database 擴充
在 RDBMS Database 相對於 Application 來說,擴充上是較不容易的(不考慮分散式系統或是讀寫分離的情況),如下圖所示
此是一個簡易的前後端分離架構圖,當用戶透過瀏覽器發送請求到資料庫處理的流程來區分,網路可以透過 CDN 快取加速,前端 FrondEnd 網站與 Backend API 可以透過 local cache 或是 Redis 等快取機制加快處理速度,當 Server 機器數量不夠時可以透過 Scale out 擴充承接更大量的 Request 請求,前面假設機器加到 50 或 100 台 server 能夠應付更大的流量,最後在做資料異動還是需要透過 Database 來處理,由於 RDBMS Database 的特性(Atomicity、Consistency、Isolation、Durability) 注重資料的一致性,因此在擴充上是較難分為多台水平擴充,如果遇到效能的問題需要做擴充大多都會選擇硬體升級方向出發,但是升級都會遇到機器物理的上限無法無止境的提升,因此保護好資料庫變成一件很重要的事情。
資源的限制
在架構的選擇中,資源(Resource)也是考量的重點之一,常見的資源有 CPU、Memory、Storage space、Disk IO、Network bandwidth、Network latency 等,請大家思考哪一個項目是覺得比較難擴充的,有人回答 Disk IO,因為 Network 的問題或許可以靠 CDN 去解決,但 Disk IO 可能跟不上 CPU 的速度,大家都提出自己的觀點與看法,接著導師請大家思考
導師 : 在雲端服務廠商裡面,上述提到的(Resource)有什麼服務是不能選擇的 ?導師提出他的觀點 Network 是無法選擇的,Google 推出 Protocol Buffers 以及 MessagePack 等新的 format 就是為了解決網路傳輸的問題,主要是透過(使用CPU)壓縮的方式讓傳輸資料輕量化,以加快資料網路傳輸的速度,也就是用 CPU 去換傳輸資料輕量化。
Queue
導師 : 甚麼時候應該要用 Queue ? 它的特性應該是什麼 ?
- 有順序性,存放暫存的請求內容(狀態state)資料
- 在架構設計上常會用於系統與系統間解偶(Loosely Coupled)
- 像是非同步,處理完畢的時間不確定 (asynchronous 的缺點都有)
Kafka & RabbitMQ
接著討論到常見的 Queue service 有 Kafka 及 RabbitMQ,分別是使用 Java 與 Erlang 不同的程式語言所開發,分別有各自程式語言的特性,像是 RabbitMQ 預設記憶體超過 40% 時會發出 memory 不足的警告,當 GC (Garbage Collection) 機制回收時會消耗兩倍記憶體量為 80% (50% used memory + 50% Crach memory,確保失敗的記憶體可以復原),這是 Erlang 程式語言的 safe to crash 的特性也是可能在使用 RabbitMQ 必須要注意的地方(缺點);接著談到 Kafka,Kafka 是 Linkedin 開發的 open source,Kafka 快的原因是 Java 有使用 off-heap,
備註1 : 當 GC 啟動在執行時記憶體回收時,正在進行的執行緒會將暫停直到 GC 回收完畢為止,為了解決內存記憶體過大造成 GC 回收時間過長的問題, JAVA 提供 off-heap memory,將記憶體放在 heap 中將控制權交由作業系統處理,(感謝 Ant 大協助 Review & 糾正)
心得
過去曾經在面試中被問到 RDBMS 與 NoSQL 如何選擇,自己當時回答得七零八落,但經過這兩次小組的討論陸續有講到 RDBMS、NoSQL與 NewSQL 的本質設計,對於這問題的答案自己也開始有些頭緒。如同於程式架構的演進一樣,從 RDBMS 到 NoSQL 到最近的 NewSQL,各有適用的強項(解決的問題)與適用的場景,沒有一招打遍天下的解決方案。另外在討論架構時也提到不同解決方案的差異,也提醒同學必須思考什麼情況下會從一種模式轉為另一種架構模式,考量的點會是甚麼,舉例來說如果架構中某個服務loading 較高時,可以選擇抽出來提高其可用性與吞吐量,其餘沒有問題的研究既有架構繼續使用,像是積木一樣做組合與分配,選擇可以解決問題的方案才是真正的王道。
參考
Elasticache : 比較 Memcached 和 Redis 的差別
Queue 的應用(4) - ManualResetEvent 與 Lock 的 BlockQueue 補完
堆外內存(off-heap),堆內存(on-heap)
Java魔法类:Unsafe应用解析
Apache Kafka 介紹
Blocking Queue
RabbitMQ性能优化
Difference between Row oriented and Column oriented data stores in DBMS
Rowise vs Columnar Database? Theory and in Practice
關聯式與NoSQL 資料
Multi-Tenancy Application #2, 資料層的選擇
Protocol Buffers
MessagePack