惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
L
LINUX DO - 最新话题
罗磊的独立博客
IT之家
IT之家
阮一峰的网络日志
阮一峰的网络日志
WordPress大学
WordPress大学
Security Archives - TechRepublic
Security Archives - TechRepublic
H
Hacker News: Front Page
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
The Hacker News
The Hacker News
Recent Commits to openclaw:main
Recent Commits to openclaw:main
大猫的无限游戏
大猫的无限游戏
PCI Perspectives
PCI Perspectives
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
Application and Cybersecurity Blog
Application and Cybersecurity Blog
P
Proofpoint News Feed
NISL@THU
NISL@THU
小众软件
小众软件
S
Security Affairs
腾讯CDC
人人都是产品经理
人人都是产品经理
C
Check Point Blog
The GitHub Blog
The GitHub Blog
有赞技术团队
有赞技术团队
Forbes - Security
Forbes - Security
Project Zero
Project Zero
G
Google Developers Blog
博客园 - 三生石上(FineUI控件)
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
博客园_首页
Jina AI
Jina AI
The Cloudflare Blog
C
Cisco Blogs
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
L
Lohrmann on Cybersecurity
Y
Y Combinator Blog
W
WeLiveSecurity
V
Visual Studio Blog
Scott Helme
Scott Helme
N
News | PayPal Newsroom
I
Intezer
C
CXSECURITY Database RSS Feed - CXSecurity.com
Attack and Defense Labs
Attack and Defense Labs
Spread Privacy
Spread Privacy
Webroot Blog
Webroot Blog
T
Threatpost
雷峰网
雷峰网
MongoDB | Blog
MongoDB | Blog
N
News and Events Feed by Topic

GentleLucky

周报 Vol.34 - 琐碎半年 · GentleLucky 2025 - 冷不丁梆梆又一年 · GentleLucky 周报 Vol.33 - 大连威海游 · GentleLucky 周报 Vol.32 - 出差上海 · GentleLucky 周报 Vol.31 - PP 吞针 · GentleLucky 忙 忙 忙 · GentleLucky 周报 Vol.29 - 浪浪山小妖怪 · GentleLucky 周报 Vol.28 - 祝你早安、午安、晚安 · GentleLucky 周报 Vol.26 - 琅琊山 · GentleLucky 周报 Vol.25 - 缺失的驱动力 · GentleLucky 周报 Vol.24 - 断工作 · GentleLucky 周报 Vol.23 - 25年第一场篮球 · GentleLucky 周报 Vol.22 - 归心似箭的心态 · GentleLucky 周报 Vol.21 - 固执己见是一座大山 · GentleLucky 周报 Vol.20 - 信封预算法 · GentleLucky 数字日记 - 自动化工作流 · GentleLucky 周报 Vol.19 - 消失的年味儿 · GentleLucky 周报 Vol.18 - 慢慢远去 · GentleLucky 个人记账管理系统(MoneyWiz) · GentleLucky 周报 Vol.17 - 2024 年终述职 · GentleLucky 周报 Vol.16 - 登黄山 · GentleLucky 2024 - 感知世界 · GentleLucky 周报 Vol.15 - 家庭网络折腾记录 · GentleLucky 周报 Vol.14 - W2X产品构建(一) · GentleLucky 周报 Vol.13 - 如何看待初创公司 · GentleLucky 周报 Vol.12 - 新徽园 · GentleLucky 从对接银行出发,如何看待实现方式? · GentleLucky 周报 Vol.11 - 《好东西》 · GentleLucky 周报 Vol.10 - 锐锐脱口秀 · GentleLucky 周报 Vol.09 - 合肥玩石银河左岸音乐节 · GentleLucky 周报 Vol.08 - 这感觉真的很奇妙吗? · GentleLucky 周报 Vol.07 - 全家福 · GentleLucky 周报 Vol.06 - 爱自己 · GentleLucky 周报 Vol.05 - 德宝病了 · GentleLucky How to write · GentleLucky 信息输入: Follow 初体验 · GentleLucky 使用 Toggl Track 做时间追踪 · GentleLucky 周报 Vol.02 - Notion 删除所有俄罗斯用户数据的思考 · GentleLucky 周报 Vol.01 - 寻找心流 · GentleLucky PP之噶🥚日记 · GentleLucky
周报 Vol.27 - 消失的成就感 · GentleLucky
作者 gentlelucky 后端 & Java研发工程师。 在 GitHub 关注我。在我的 Telegram 频道了解更多。 · 2025-07-22 · via GentleLucky

前言

本篇是对 2025-05-192025-07-20 这段时间生活的记录和思考。

某灵工结算系统规划设计「内部记账本功能」,完成了需求分析、架构设计、代码开发、到最终的成功上线,但内心毫无成就感;

消失的成就感

需求分析

客户希望「结算平台」能够拥有独立的「内部记账本功能」,即同一个「主体账号」,系统基于「主体账号」给每一个客户创建独立的「虚拟子账号」;

举例:甲客户给「主体账号」 充值了 88 元,乙客户给「主体账号」 充值了 66 元,此时「主体账号」金额 154 元。「结算平台」要区分出来「主体账号」中 88 元属于甲客户的余额,66 元属于乙客户的余额。并且支持独立的转账、充值、提现等功能。

由于自己对「内部记账本」功能没接触过,所以没有经验。于是参考了一些技术文章,设计了出版的技术概要。

image-20250721164451653

image-20250721164620348

当刚了解到这个需求后,我做了如下分析:

  • 该功能涉及到「钱」的流转,如果控制不好,会导致多发,算重大事故
  • 该功能的实现,现有的程序架构已不满足,需重新设计

通过分析,决定如下:

  • 预留充足的任务周期:立刻启动「内部记账本」项目,用来多轮测试和验证。并合理的安排任务及任务负责人。
  • 核心逻辑:
    • 对接三方结算系统(银行、支付宝…)
    • 内部记账本核心逻辑(线程安全、余额一致性)

研发任务

在线文档

使用「腾讯在线文档」的智能表格来分配任务。

image-20250722144215559

先新建一个「ALL-表格」,把所有任务罗列进去,便于全局查看任务。每个任务尽可能的控制在一人天,这样能够更加细粒度的把控任务进度。当出去任务延期时,也可快速察觉和纠正。

今天-看板:用来查看当天有哪些任务需要完成

本周-看板:用来查看本周有哪些任务需要完成,周维度查看直观的查看到本周的任务是否有堆积情况

未完成-看板:查看所有过期未完成的任务,次看板任务越多,就需要采取措施:投入更多的时间(加班)、投入更多的人力资源(加人 )

姓名-看板:个人负责的任务看板,方便个人了解自己研发任务及计划

概要设计

image-20250722142600474

通过对需求的分析,编写了内部记账本概要设计,主要涵盖表设计流程说明余额设计充值设计

概要设计能够快速拉通与研发个人的认知偏差,统一代码实现逻辑。

核心设计

结算通道对接

内部记账本需要对接多结算渠道:招商、支付宝、平安……,并且都会调用各结算渠道的代发、代发状态查询、回执单下载等接口。

针对于各种类型的结算通道,使用枚举类。

@Getter
@AllArgsConstructor
public enum SettlementChannel {
    CMB("CMB","招商银行"),
    PAB("PAB","平安银行"),
    ALI_PAY("ALI_PAY","支付宝");
    private final String code;
    private final String name;
}

对于不同结算渠道代发的实现方式不同,定义统一的接口,使用策略模式来获取对应的具体实现。

public interface Transfer {
  
    /**
     * 结算通道
     * @return {@link SettlementChannel}
     */
    SettlementChannel channel();

    /**
     * 代发
     * @param request {@link TransferRequest}
     * @return
     */
    TransferResponse transfer(TransferRequest request);

}
@Component
public class TransferFactory implements InitializingBean {

    @Resource
    Collection<Transfer> transfers;
    private Map<SettlementChannel, Transfer> transferMap;

    public Transfer get(SettlementChannel channel) {
        Transfer transfer = transferMap.get(channel);
        if (Objects.isNull(transfer)) {
            return null;
        }
        return transfer;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        this.transferMap = IterUtil.toMap(transfers, Transfer::channel);
    }
}

余额设计

余额存在同一时刻并发操作:支出、充值;所以余额变更需是线程安全的;

public class DefaultAccountBookLock implements AccountBookLock {
    // 账户类
    private volatile CashbookAccountBook cashbookAccountBook;
    // 锁
    private final ReentrantLock lock;
    // 初始化
    public DefaultAccountBookLock(CashbookAccountBook cashbookAccountBook) {
        this.cashbookAccountBook = cashbookAccountBook;
        this.lock = new ReentrantLock();
    }
    // 加锁
    @Override
    public void lock() {
        lock.lock();
    }
    // 释放锁
    @Override
    public void unlock() {
        lock.unlock();
    }
}

定义AccountBookLock类,核心操作是ReentrantLock加锁和释放锁逻辑。一个账号对应一个锁。这样可保证在并发下线程是安全的。

@Slf4j
@Service
public class AccountBookManager implements AccountBook, InitializingBean {
    // 账户锁
    private final ConcurrentHashMap<String, AccountBookLock> accountLocks = new ConcurrentHashMap<>();

    /**
     * 创建账户,账户信息存并发安全的ConcurrentHashMap中
     * @param cashbookAccountBook
     * @return
     */
    @Override
    public void create(CashbookAccountBook cashbookAccountBook) {
        accountLocks.computeIfAbsent(cashbookAccountBook.getAccountBookId(),
                o -> new DefaultAccountBookLock(cashbookAccountBook));
    }

		// 代发
    @Override
    public void payroll(String accountBookId, BigDecimal rechargeAmount, BigDecimal frozenAmount) {
        AccountBookLock accountBookLock = this.getAccountBookLock(accountBookId);
        try {
            accountBookLock.lock();
            log.info(">>> [记账本][余额] 代发开始 | accountBookId={}", accountBookId);
						// 代码逻辑......
            log.info(">>> [记账本][余额] 代发结束 | accountBookId={}", accountBookId);
        } finally {
            accountBookLock.unlock();
        }
    }

    
    private AccountBookLock getAccountBookLock(String accountBookId) {
        AccountBookLock accountBookLock = accountLocks.get(accountBookId);
        if (accountBookLock == null) {
            log.error("[记账本][余额] 账户不存在 | accountBookId={}", accountBookId);
            throw new ServiceException("账户不存在");
        }
        return accountBookLock;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // 初始化数据
        for (CashbookAccountBook accountBook : list) {
            this.create(accountBook);
        }
    }

}

AccountBookManager统一对外操作余额接口,先使用「accountBookLock.lock()」方法对方法加锁,业务逻辑执行结束后,在 finally 代码块中释放锁「accountBookLock.unlock()」,从而实现了对余额进行的线程安全操作。

回退方案

针对每一次大版本的迭代上线,一定要考虑如何当上线版本出现重大问题,如何快速回退到上一个版本。

  • 数据库层面
    • 备份当前数据
    • 尽量不要修改已使用字段含义
  • 程序层面
    • 如果条件允许,可使用配置文件切换新旧代码版本
    • 做好上一个版本的程序备份
  • 人员层面
    • 提前告知相关人员,如果回退,大家各尽其责

成功上线

6 月底完成了研发测试工作,7 月 18 日迭代上线。

当晚上线还算比较顺利,上线后系统稳定运行,未出现结算多发、少发、余额不一致情况。

总结反思

上一份周报停留在 2025-05-18 那一周,大部分原因是由于「内部记账本」研发周期严重偏离了原计划。导致自己大部分时间都投入到研发工作中,没有太多心思和精力去写博客了。

研发周期严重偏离计划有如下原因:

  • 个人出差半个月,没精力去统称计划
  • 研发对「内部记账本」需求理解偏差,导致返工
  • 研发对「余额」变更的逻辑设计存在缺陷

原计划中,我是「项目管理」的角色。但后期又以研发的角色加入项目,编写了:

  • 结算通道对接代码(招商、支付宝)
  • 余额并发安全代码
  • 记账本业务代码
  • 测试联调bug修复

从本次项目,我收获到:

  1. 当自己有其他事情时,可把当天项目委托给另一个靠谱的人暂时托管
  2. 当核心逻辑研发人员提出自己的设计时,存在不合理时,要否定。要不然会导致项目后期,加班去推翻逻辑重写
  3. 概要设计要尽可能的详细,这样可减少需求偏差

成就感

bae3bc0cd26bb00a9e484ad1bb79284c

2016 年 7 月 17 日,完成了「志邦7·17」现场抽奖大屏项目。当时成就感满满,那种发自内心的开心和喜悦是无法用言语表达出来的。

2025 年 7 月 18 日,「内部记账本」成功上线;内心却毫无波澜,没有任何成就感。即使「内部记账本」的技术难度比「志邦7·17」高了好几个 Level,也并不会因为技术提升而感到骄傲。

我不知道这种状态是否正常,我也不知道什么样的工作任务,能让我找到之前「成就感」的初心。

有趣的事与物

输入

虽然大部分有意思的输入会在 「Lucky’s Footprints」 Telegram 频道里自动同步,不过还是挑选一部分在这里列举一下。并且把 Telegram Channel 消息作为内容源搭建了一个微博客 —— 「daily.gentlelucky.com」,可以更方便浏览了。

收藏

  • The Everything App,Obsidian平替方案

视频

音乐

  • III (Find Yourself) - Athletics
  • 回不去的夏天 - 夏日入侵企画

文章

  • 独立开发出海,需要点哪些技能树 | 辣条的博客

影视

  • 哈哈哈哈哈 第五季
  • 长安的荔枝