Go劍復國-30天導入Golang Day29 如何設計一個非阻塞式的扣款系統
我相信在很多系統上,很多效能瓶頸會在 database ,尤其是一些帳戶系統,如果無法解決扣款時 ACID 的相關議題,那壓力其實最終都會壓在 database 的單點上,在敝公司設計這相關系統時,我使用了另一個方式來做設計。當然下面介紹的東西,要用其他語言實現也不是不行,不過敝公司是選擇使用 golang 實現就是了。
首先我們先看下面的圖,這是一張我個人覺得蠻標準的一個扣款系統大致上的架構
就如上面所講的,當大量 request 進來時,紅色區塊(wallet)的地方,會造 loading 最重的地方,而且如果當 database latency 開始拉高時,會開始出現雪崩效應,連帶的連前面的 application 、 load balance,都會因為 database 而開始出現堆連線的情況。在這種情況下,整個系統全部 crash 都有可能。
接下來我們試著想想,如何不讓 database latency,而且可以讓 application 可以很快的處理完連線,並且釋放掉它,避免堆連線的情況,所以我導入了 Message Quene,來幫助我達成這件事情,我們先看看架構圖
關於 Message Quene 我列了下面優點
- 解偶 (A服務不用認識服務 etc…)
- 靈活性 (B服務需要知道服務的一些資訊,不需要A服務另外開接口)
- 擴展性 (可以做到類似gearman 派工分散處理)
- 緩衝 (一瞬間大量耗資源處理的需求進來,可以buffer住)
- 異步處理 (大量耗資源處理需求進來,不會讓請求端卡住)
由上面可以看到,透過 Message Quene 的協助,並且用出 producer、consumer 來協助減壓 wallet,在這個設計的理念上 user 其實並沒有馬上收到扣款成功的 response ,而是透過其他機制來做通知,user 當下只會收到扣款『預約』,並不代表完成扣款,當然這個機制,就看商業上的需求,也許可以用 websocket 即時同知,或是請 user 去其它頁面來做查詢。
敝公司在 Message Quene 的選擇上,是選擇 nsq,為什麼選擇它呢?
- golang 撰寫
- 非常容易 scalable
- 架設非常容易
當然 Message Quene 在市面也有非常多的選擇,這邊稍微列一下我所知道的
- RabbitMQ
- NSQ
- Kafka
- Redis
運用 Message Quene 可以就可以非常容易使用事件驅動(event trigger),在運用上非常的彈性,我非常推薦在系統的架構設計上,加入這個元素,可以讓整個系統更富有彈性。