找回密码
立即注册
搜索
发回帖 发新帖

4835

积分

0

好友

623

主题
发表于 1 小时前 | 查看: 5| 回复: 0

某节员工吐槽,外人一听年薪60万,往往下意识除以12,得出月薪5万。但在互联网公司的薪酬结构里,60万可能包含基本工资、季度奖、年终奖、股票等多个部分,实际每个月到账的固定收入并不是这个数字。

字节员工吐槽年薪60万实际构成截图

这个问题放到技术团队里也很像:一个系统看起来“价值很高”,可能只是堆叠了很多隐含成本。真正接手维护时,才发现核心逻辑藏在定时任务里,数据一致性依赖人工操作,服务稳定性依赖某几个开发人员的记忆。

我之前维护过一个订单结算系统,早期业务量不大,设计非常直接。订单完成后,同步调用结算服务:

@Transactional
publicvoidfinishOrder(Long orderId){
    Order order = orderMapper.queryById(orderId);

    orderMapper.updateStatus(orderId, "FINISH");

    settlementService.createSettlement(order);
}

这个设计在初期确实没什么问题。订单量每天几千笔,结算逻辑简单,同步执行还能保证用户看到订单完成后,结算一定生成。代码少,链路短,排查也方便。

但后来业务增加了优惠券、分销佣金、渠道返点几个模块,结算逻辑持续膨胀。代码慢慢变成这样:

publicvoidcreateSettlement(Order order){
    BigDecimal amount = calculateAmount(order);

    BigDecimal coupon = couponService.queryDiscount(order.getId());

    BigDecimal commission = commissionService.calculate(order);

    BigDecimal channelFee = channelService.calculate(order);

    settlementMapper.insert(
        buildSettlement(order, amount, coupon, commission, channelFee)
    );
}

表面看只是多了几个计算,实际上整个订单完成接口已经承担了太多职责。线上一次问题就是从这里开始暴露的。用户反馈部分订单已经显示完成,但是结算金额几个小时后才出现。

最开始我们怀疑数据库锁,先查看慢SQL:

select *
from settlement_record
where order_id = ?
andstatus = 'INIT';

执行时间正常。继续看数据库监控,也没有明显锁等待。后来查看调用链:

order-service
 |
 |-- settlement-service
       |
       |-- coupon-service
       |
       |-- commission-service
       |
       |-- channel-service

发现订单完成接口平均耗时从300ms增加到了3秒以上。原因不是数据库,而是同步调用链变长。其中一个渠道服务偶发响应超过2秒,导致整个订单流程被拖慢。

当时调整的第一步不是直接引入复杂架构,而是先拆开职责。订单完成只负责状态变化,结算任务异步处理。在数据库中增加业务状态:

altertable order_info
addcolumn settlement_status varchar(20)
default'WAITING';

订单完成逻辑变为:

@Transactional
publicvoidfinishOrder(Long orderId){
    orderMapper.updateStatus(orderId, "FINISH");

    settlementTaskMapper.insert(
new SettlementTask(orderId, "WAITING")
    );
}

后台线程消费任务:

@Scheduled(fixedDelay = 1000)
publicvoidexecuteSettlement(){

    List<Long> ids =
        settlementTaskMapper.queryWaitingTask(100);

for (Long id : ids) {
try {
            settlementService.createSettlement(id);

            settlementTaskMapper.success(id);

        } catch (Exception e) {

            log.error(
"settlement failed, orderId={}",
                id,
                e
            );

            settlementTaskMapper.retry(id);
        }
    }
}

改完以后,订单主流程恢复稳定。但新的问题紧接着来了:任务失败重试时,可能重复生成结算记录。比如第一次执行:

create settlement
insert success
update task status failed

任务状态没有更新成功,下一次执行又会插入一条。所以结算表需要增加唯一约束:

altertable settlement_record
adduniquekey uk_order_id(order_id);

代码层增加幂等控制:

publicvoidcreateSettlement(Long orderId){

    SettlementRecord record =
        settlementMapper.queryByOrderId(orderId);

if (record != null) {
return;
    }

    settlementMapper.insert(
        buildSettlement(orderId)
    );
}

这里其实有个工程上的取舍。很多系统的问题不是代码写错,而是原来的设计只适用于当时的业务规模。同步调用没有错,固定工资和奖金组成的薪酬结构也没有错,问题在于随着规模变化,隐藏部分开始影响整体结果。

后来我们又补充了任务监控,每天检查:

selectcount(*)
from settlement_task
wherestatus='WAITING'
and create_time < now() - interval10minute;

超过阈值报警。因为真正影响系统稳定性的,往往不是某一行代码,而是那些没有被记录、没有被监控、只能靠某个人记忆的部分。

回到年薪结构这个话题,系统成本也一样,不能只看表面数字。在云栈社区的技术讨论里,类似的话题也经常被提起——一个服务值不值得依赖,要看它背后的代码质量、稳定性机制和维护成本。




上一篇:AI 时代审美练习(下):从浮世绘到 AI 生图,如何建立自己的品味?
下一篇:15万星的ponytail:用"七级台阶"让AI智能体少写54%的代码
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-10-5 07:59 , Processed in 0.072928 second(s), 38 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表