有网友吐槽,离职前在工作群里发了一段告别消息,结果主管直接回了一句:“你走就走,没必要发这些废话,没人会记得你。”

这类冲突在技术团队里其实并不少见。一个开发离开,真正暴露的问题往往不是告别消息有没有人回复,而是某个服务、某段业务规则、某个线上处理流程,是不是也跟着这个人一起消失了。
我之前维护过一个订单系统,某个核心优惠计算模块长期由一名开发负责。平时看不出什么问题,代码也能正常跑,但等到这个开发离职后,新同事第一次接手改规则,线上立刻出现了大量订单金额异常。排查之后发现,系统最大的风险不是代码写得差,而是关键业务知识没有沉淀到代码和机制里。
当时这个优惠服务的逻辑大概类似这样:
public BigDecimal calculateDiscount(Order order) {
if (order.getUserLevel() == 3
&& order.getCreateTime().isAfter(activityStartTime)) {
return order.getAmount()
.multiply(new BigDecimal("0.8"));
}
return BigDecimal.ZERO;
}
光看代码只是一个简单判断,但线上规则远比这个复杂。
会员等级、活动时间、渠道来源、历史参与记录都会影响最终优惠结果。以前这些条件都存在开发人员的脑子里,代码只是最后执行的一部分。后来新需求要求增加“同一用户每天最多享受一次优惠”,接手的同事直接加了逻辑:
@Transactional
public void createOrder(Order order) {
BigDecimal discount = discountService.calculateDiscount(order);
order.setDiscount(discount);
orderMapper.insert(order);
discountRecordMapper.insert(
new DiscountRecord(order.getUserId(), discount)
);
}
上线当天就出现了重复优惠。
第一反应是怀疑数据库事务问题,因为优惠记录和订单写入在同一个事务里,乍一看没有明显漏洞。
检查 MySQL 慢查询,没有异常。
检查事务提交日志,也没有回滚。
继续看调用链:
order-service
|
|-- discount-service
|
|-- redis 查询用户优惠次数
|
|-- mysql 保存优惠记录
最终发现问题出在 Redis 查询环节。
原来的逻辑为了降低数据库压力,加了一层缓存:
String key = "discount:" + userId;
Integer count = redisTemplate.opsForValue()
.get(key);
if (count != null && count >= 1) {
return false;
}
但是优惠成功后,数据库记录增加了,Redis 却没有同步更新。
结果就是:
第一次请求:
Redis: null
MySQL: insert discount_record
第二次请求:
Redis: null
MySQL: insert discount_record
数据库里出现两条优惠记录。
这里的问题并不是 Redis 用错了,而是原来的设计依赖人工记忆。那个离职开发知道:“优惠成功后必须清缓存。”但系统不知道。
后来我们调整了实现,把业务状态从人的经验里拿出来。优惠记录写入后,通过统一方法更新缓存:
@Transactional
public void saveDiscountRecord(Long userId, BigDecimal amount) {
DiscountRecord record =
new DiscountRecord(userId, amount);
discountRecordMapper.insert(record);
String key = "discount:" + userId;
redisTemplate.opsForValue()
.set(
key,
getTodayDiscountCount(userId),
24,
TimeUnit.HOURS
);
}
同时增加数据库唯一约束,避免代码异常情况下产生重复数据:
ALTER TABLE discount_record
ADD UNIQUE KEY uk_user_day(user_id, discount_day);
这样即使缓存失效,数据库也有最后一道保护。
线上系统里,很多所谓“某个人走了没人接”的问题,本质都是知识没有进入系统。一个开发熟悉某个模块,并不代表系统可靠;可靠的系统应该让新人通过代码、日志、监控和约束快速理解,而不是靠老人临走前交代几句“注意清缓存”。
后来我们还补充了关键业务日志:
log.info(
"discount apply userId={}, orderId={}, amount={}, rule={}",
userId,
orderId,
discountAmount,
ruleVersion
);
出现问题时,不需要再依赖某个人解释“当时为什么这么写”。
回到离职告别这件事,Redis 这类基础设施上的坑,往往不是技术本身有多难,而是团队把太多隐性知识留在了个人身上。真正需要沉淀的,从来不是某个人的脑内经验,而是代码、流程和机制。