记一次API的BUG
BUG简述
API完成一个相对较重的功能,用户使用API的时候需要扣除相应的权限次数,由于流程设计不合理,导致可能出现「一次权限多次使用」的情况。
第一版的流程如下:
sequenceDiagram APP->>Server: 提交 Server-->>Server: 权限确认 Note right of Server: 用户可能在此时频繁发起提交请求 Server->>AI Engine: 作文 Note left of AI Engine: 耗时大概3秒 activate AI Engine AI Engine->>Server: AI结果 Server-->>Server: 存储结果以便用户后续查看 Server-->>Server: 扣除次数 Server-->>APP: 返回结果
错误情况: 用户只有一次权限时,可以在「确认权限」但AI处理的间隙,快速提交多个不同请求,这是仍然够得到结果并存储。产生了一次权限多次使用的情况。
可以有多种方式处理这个问题,需要根据实际情况,选择能解决当下绝大部分问题,又成本较低的方式。
便有了第二版流程:
sequenceDiagram APP->>Server: 提交 Server-->>Server: 权限确认 Note right of Server: 用户可能在此时频繁发起提交请求 Server->>AI Engine: 作文 Note left of AI Engine: 耗时大概3秒 activate AI Engine AI Engine->>Server: AI结果 Server-->>Server: 扣除次数,如扣除成功则储存结果 Server-->>APP: 返回
选择此方式的原因:
- 当前只是用户在客户端的非正常流程中产生的,如前端loading未正常显示,导致在返回结果前用户可以重复提交。
- 修复后,用户看到的逻辑是正常的,即一次权限能提交完成一次。即便AI Engine有因BUG而带来的重复调用,从成本上看,可以忽略不计。
启发
- 多种操作的事务化是个难题,实际中,既要保持高效,又要避免或处理「部分完成」情况。大多数时候,要根据具体情况权衡处理,要多分析结果数据。
- 业务上线初期,多看各个层面的数据是有必要,能够发现很多隐晦的问题。避免累积成,严重的问题。
- 事务处理通常有两派处理方式:
- 乐观派:线上不做处理,不保证事务性,通过定期的离线脚本对账,多退少补。例如,广告平台大多通过这样的方法统计结算数据。
- 悲观派:线上保证强事务性,通常需要锁机制和回退操作。例如,支付的交易系统,要实时保证出账入账的一致性。