[ 玩轉 LeanCloud ] 開發者經驗分享:後端
做者:Davy微信
咱們的產品叫「學海密探」,屬於在線教育行業,產品須要有支付功能,然而支付最蛋疼是什麼?有人會說是支付寶和微信等支付接口的接入開發!沒錯,但支付接口的開發算是比較簡單的了,我以爲凡是跟錢有關係的操做最重要的是事務問題,這一點很重要,很重要,真的很重要!LeanCloud 官方文檔中有提到 MongoDB 不支持事務,並建議對事務有強烈需求的開發者使用其餘折中方式來實現。咱們的支付必須用事務,咱們通過 N 輪討後論設計了一套基於 LeanCloud 的支付場景的通用解決方案,也許其餘團隊比咱們作得好,在這裏仍是分享下咱們的一些看法吧。併發
咱們在用戶表 _User 中加入了一個 paylogs 字段,類型是 Array,主要用於存放着每一次支付日誌的 id,用它來判斷用戶的帳戶 account 的值,好比錢扣沒扣,加沒加等狀況。由於在支付過程當中不能保證每一次操做都成功,因此還要引入一個日誌表 log 來作數據的一致性,保證用戶資金變更與實際相符。log 表裏有一個「狀態」字段 state,它的取值爲 0 ~ 5,主要是從發起支付開始,生成 order 表,生成 log 表等,並記錄 log 的狀態,後續全部的業務都要根據 state 的狀態執行不一樣的業務操做,無論在哪一個狀態出問題均可以根據 log表的 state 狀態重複執行相應的業務操做,從而保證支付過程的數據一致性!設計
好比在充值的時候,用戶扣費成功後,修改用戶的 account 值成功了,但在修改 state 字段時失敗了,下一次再執行時又怎麼判斷用戶的 account 值已經改變了呢?這個問題真是過重要了,這就要用到那個 paylogs 字段,判斷 paylogs 字段是否有值,有值說明剛纔用戶的 account 值已經操做過了,此時能夠不用操做,若是沒有再進行操做。這裏利用了 LeanCloud 數據存儲接口的按條件更新數據的功能(使用 query 參數)來保證操做的原子性,從而也解決了併發問題!這個 query 參數真得要誇一下,在 LeanCloud 還沒提供這個功能以前,咱們只能採用 log 表中的新舊值比對來解決數據一致問題,但沒法避免併發問題,這樣當用戶數據錯了,咱們只能認爲支付失敗,而後進入人工干預環節,非常麻煩。日誌
最後再說說咱們和 LeanCloud 的相遇。最初是經過朋友圈知道了 LeanCloud,後來就一直關注着。也試過一些項目,發現開發應用真是方便許多。本來大量的後端需求都要本身研發,如今都省了,只須要專一於寫應用端的代碼,效率天然會提升一倍以上,開發迭代速度也上去了。固然也有過顧慮,生怕遇到一些特殊場景 LeanCloud 知足不了那咱們就悲劇了!但後來看到一些知名的應用都在用 LeanCloud,內心也就安穩了,有前輩們踩過坑,有 LeanCloud 的技術支持作後盾,咱們就這樣選定了 LeanCloud。接口
隨着項目的進行,咱們從傳統的後端服務接口開發變成了面向「Document」開發,服務端工做減輕了很多。雖然在數據設計中遇到一些複雜結構的問題,好比 Pointer 和 Relations 的問題。記得當時 Array 不支持 Pointer 的 include,因此考慮用 Relations,但在 LeanCloud 社區中又看到幾個相關問題都推薦使用 Array 或者 Pointer,後來通讀了相關文檔對數據模型有了更深的理解,問題也就少了,因此說全面瞭解文檔是相當重要的。事務