国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

賬戶變動合并提交方案

MoAir / 3039人閱讀

摘要:起因及介紹在早期的賬戶系統(tǒng)中,但凡有賬戶變動,就會執(zhí)行一次數(shù)據(jù)庫操作。這時,在一次處理過程中,合并同一個賬戶的所有操作,最后只提交一次,就能帶來很大的優(yōu)化空間。根據(jù)業(yè)務(wù)需要,進(jìn)行增減轉(zhuǎn)賬凍結(jié)解凍操作。

起因及介紹

在早期的賬戶系統(tǒng)中,但凡有賬戶變動,就會執(zhí)行一次數(shù)據(jù)庫操作。這樣在有復(fù)雜一些業(yè)務(wù)操作的時候,例如單筆交易涉及多個用戶多個費(fèi)用的資金劃撥,一個事務(wù)內(nèi)操作數(shù)據(jù)庫幾十次也就大量的存在。而觀察這樣的場景,其本質(zhì)可能只涉及少數(shù)幾方的賬戶。
這時,在一次處理過程中,合并同一個賬戶的所有操作,最后只提交一次,就能帶來很大的優(yōu)化空間。

處理方法

1. 初始化一個收集器ExecuteParam,用來存放有變動的賬戶、待新增的資金記錄、待處理的凍結(jié)數(shù)據(jù)和待新增的凍結(jié)記錄。

final ExecuteParam param = ExecuteParam.instance();

public class ExecuteParam {
    private final Map cache = Maps.newHashMap();
    private final List financeLogs = Lists.newArrayList();
    private final Map freezeRecords = Maps.newHashMap();
    private final List freezeHistorys = Lists.newArrayList();

    public static ExecuteParam instance() {
        return new ExecuteParam();
    }

    public Map getCache() {
        return cache;
    }

    public List getFinanceLogs() {
        return financeLogs;
    }

    public Map getFreezeRecords() {
        return freezeRecords;
    }

    public List getFreezeHistorys() {
        return freezeHistorys;
    }
}

2. 根據(jù)業(yè)務(wù)需要,進(jìn)行增、減、轉(zhuǎn)賬、凍結(jié)、解凍操作。

public interface FundTransactionService {
    /** 調(diào)增 */
    void addCredit(TransactionCommandParam command, final ExecuteParam param);

    /** 調(diào)減 */
    void addDebit(TransactionCommandParam command, final ExecuteParam param);

    /** 轉(zhuǎn)賬 */
    void addTransfer(TransactionCommandParam command, final ExecuteParam param);

    /** 凍結(jié) */
    String addFreeze(TransactionCommandParam command, final ExecuteParam param);

    /** 解凍 */
    BigDecimal addUnfreeze(TransactionCommandParam command, final ExecuteParam param);

    /** 更新DB */
    void execute(String proofId, ExecuteParam param);
}

public static TransactionCommandParam createTransfer(...);

public static TransactionCommandParam createFreeze(...);

public static TransactionCommandParam createUnfreeze(...);

public static TransactionCommandParam createCredit(...);

public static TransactionCommandParam createDebit(...);

3. 所有資金操作在底層都按照:校驗(yàn)操作類型->修改賬戶余額->資金記錄的流程執(zhí)行

@Override
public void addCredit(TransactionCommandParam command, final ExecuteParam param) {
    /** 1.校驗(yàn) */

    /** 2.調(diào)賬 */
    FinanceAccount receiverFa = credit(command.getReceiverOwnerId(), command.getReceiverRoleId(), command.getAmount(), param.getCache());

    /** 3.資金記錄 */
    param.getFinanceLogs().add(...);
}

4. 其中修改賬戶余額的方法,會先嘗試從ExecuteParam中查找該賬戶是否已經(jīng)被操作過,如果沒有才查詢一次DB。這樣就確保了同一個賬戶在一次處理過程中,無論有多少資金操作,只會查詢一次DB。

private FinanceAccount credit(Long ownerId, Long roleId, BigDecimal amount, Map cache) {
    final String cacheKey = getCacheKey(ownerId, roleId);
    FinanceAccount fa = cache.get(cacheKey);
    if (fa == null) {
        // 此處只查詢一次DB
        fa = getFinanceAccount(ownerId, roleId);
        cache.put(cacheKey, fa);
    }

    // 調(diào)增:
    fa.credit(amount);

    return fa;
}

5. 當(dāng)所有業(yè)務(wù)操作完成之后,一次性提交本次處理過程中的所有賬戶

fundTransactionService.execute(proof.getProofId(), param);

@Override
public void execute(String proofId, ExecuteParam param) {
    /** FinanceAccount統(tǒng)一更新 */
    for (FinanceAccount account : param.getCache().values()) {
        account.setProofId(proofId);

        // 熱點(diǎn)賬戶延遲更新
        if (isHotAccount(account.getId())) {
            continue;
        }

        // DB update
        this.updateAccount(account);
        logger.info("賬戶更新[{}]", account);
    }

    /** FinanceLog統(tǒng)一批量記錄 */
    financeLogDao.addFinanceLog(param.getFinanceLogs());

    /** 凍結(jié)記錄統(tǒng)一批量更新 */
    for (AccFundManagementRecord freezeRecord : param.getFreezeRecords().values()) {
        if (freezeRecord.getId() != null) {
            // DB update
        } else {
            // DB insert
        }
        logger.info(LoggerUtil.createInfoLog("execute","凍結(jié)記錄[{}]"), freezeRecord);
    }

    /** 凍結(jié)歷史統(tǒng)一批量更新 */
    for (AccFundManagementHistory history : param.getFreezeHistorys()) {
        // DB insert
    }
}
總結(jié)和思考

這次優(yōu)化不僅大幅減少了數(shù)據(jù)庫的負(fù)擔(dān),而且也因?yàn)閿?shù)據(jù)庫訪問次數(shù)少了,處理速度也快了(例如還款,原先的處理時間約為1到2s,優(yōu)化后的處理時間約為40ms)。處理速度快了,使用樂觀鎖控制的并發(fā)異常也相應(yīng)減少了。

另外值得思考的地方是,在第一步初始化收集器ExecuteParam的時候,將所有容器都創(chuàng)建出來了,并不是所有業(yè)務(wù)都會用到全部的容器,這里是否有必要?

我的想法是讓步于開發(fā)便利性。
誠然是可以根據(jù)不同的場景有選擇性的初始化相應(yīng)的容器,但是這樣開發(fā)人員在使用的時候需要思考的更多,需要做選擇,不夠簡單明了。而且省去一兩個容器的初始化帶來的好處可以并不大。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/77292.html

相關(guān)文章

  • 熱點(diǎn)賬戶解決方案

    摘要:全局熱點(diǎn)賬戶平臺支出賬戶平臺收入賬戶過渡賬戶。。那么親,這和熱點(diǎn)賬戶沒關(guān)系,即使你查詢一個非常普通的賬戶,碰巧該賬戶同時在更新,你也查不準(zhǔn)。。 問題描述 在某一瞬間,單個賬戶集中的發(fā)生資金變動,若不加控制,其賬戶余額會因發(fā)生臟讀、覆蓋更新等情況而錯誤記錄。如果簡單的以悲觀鎖、樂觀鎖的方式限制,雖然不會發(fā)生數(shù)據(jù)錯誤,但會造成服務(wù)不可用(該賬戶的更新請求全部失?。?。而請求重試、再次網(wǎng)絡(luò)通信...

    MycLambert 評論0 收藏0
  • 【強(qiáng)烈推薦】程序猿開發(fā)工具(第二期)

    摘要:這允許開發(fā)人員以邏輯區(qū)間建立并提交變動,以防止當(dāng)部分提交成功時出現(xiàn)的問題納入版本控管的元數(shù)據(jù)每一個文件與目錄都附有一組屬性關(guān)鍵字并和屬性值相關(guān)聯(lián)。 代碼管理 Git...

    KevinYan 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<