假設現存在一個簡單的猜大小遊戲,由用戶下注大或者小,扣除手續費3%後的錢所有放入獎池中,贏的一方按投注比例平分整個獎池。使用mysql做爲數據庫,系統精度精確到1位小數。
本文將會講解其中會出現的業務結算致使的數據問題,以及解決方法。mysql
系統內應該存在一個用戶錢包表,其中指定兩條記錄爲系統收入帳戶和系統撥出帳戶。這樣能夠將投注的時候,對系統帳戶餘額增長操做,和發獎的時候,對系統帳戶餘額的減去操做分離。sql
能夠避免上一期遊戲的結算,對下一期遊戲的投注發生鎖等待的問題。數據庫
考慮到高併發的狀況下,推薦使用mysql自帶的排他鎖,不推薦樂觀鎖,由於樂觀鎖須要重試機制,而隊列結算暫時不考慮。
當一名用戶發起投注的時候,檢查順序應該以下併發
這裏之因此要冗餘檢查用戶的額度,是否了避免開啓事務的消耗,防止惡意攻擊消耗系統資源,用來開啓無心義事務。高併發
獎池額度的97%這裏計算須要保持一位精度,若是用戶投注是98,按照計算獲得的值應該是95.06,咱們應該取95.0而不是95.1,不然你最後存到獎池裏面的數就會大於97%,這樣系統抽取就不會達到3%,用戶少分點不要緊,要保證系統必定能分到3%。設計
簡單一句話就是:精度位後都捨棄隊列
假設按照投注比例,瓜分出的獎金總數是22.1,A用戶的份額是55.5%,A用戶拿到12.2655,B用戶的份額是45%,B用戶拿到9.8345。遊戲
這種狀況下,你會發現,按照捨棄,原則,分別是12.2和9.8,結果是隻發放了22,若是你按照四捨五入原則,才能發放到22.1事務
那爲何還要堅持捨棄原則呢?由於,假設出一個極端狀況,當你碰到A的值是12.05,B的值是9.05,按照捨棄原則,總數的確仍是22.1。可是按照四捨五入原則,發放的總值就是22.2了。資源
在計算機系統內,浮點數的計算自己就是不可靠的,在業務內應該用整形去避免,當設計到百分比操做的時候,請儘可能使用捨棄原則,保證很少發。按照捨棄原則,給用戶少發0.05這種精度外的值,對業務來講可有可無。若是超發了,會致使系統內帳目混亂,後果將不堪設想。