好友关系变更场景下双类型事件发布的推荐实现方案咨询
优化方案建议
你的初始方案是可行的,但可以从减少数据库查询、保证操作原子性两个维度优化,具体如下:
核心优化思路:提前计算变更明细,避免额外查询
你的原方案步骤3需要再次查询数据库获取全量好友列表,实际上如果这个PATCH接口的语义是设置最终好友集合(从你的示例来看确实如此),那么请求体中的friends数组就是更新后的最终全量,完全可以省去这一步查询。优化后的流程:
- 查询数据库中当前的好友集合(
currentFriends) - 对比请求体的目标集合(
targetFriends),计算出Added(targetFriends - currentFriends)和Removed(currentFriends - targetFriends) - 执行数据库更新,将好友集合替换为
targetFriends - 发布
FriendsUpdated事件,直接使用targetFriends作为Friends字段值 - 发布
FriendsChanged事件,携带计算好的Added和Removed明细
这个优化的好处是减少了一次数据库读操作,提升性能;同时避免了更新后查询可能遇到的并发数据不一致问题(比如更新完成后,其他请求刚好修改了好友列表,导致查询到的不是自己更新后的结果)。
关键注意事项
并发冲突处理
为了避免多请求同时修改导致的变更明细计算错误,建议给用户好友表加乐观锁(比如增加version字段):查询currentFriends时同时获取版本号,更新时校验版本号是否匹配,不匹配则返回冲突错误,让客户端重试。事件与数据库操作的原子性
必须保证「数据库更新成功」和「事件发布成功」的原子性,否则会出现数据与事件不一致的情况。常用方案:- 使用支持事务的消息中间件(如Kafka事务),将数据库更新和事件发送放在同一个事务中
- 采用「本地消息表」方案:先将事件写入数据库的消息表,再执行好友列表更新,最后通过异步任务将消息表中的事件发送到消息队列;如果更新失败,消息表的记录可以回滚,避免脏事件。
事件命名的语义一致性
你的FriendsUpdated(全量)和FriendsChanged(明细)命名清晰,也可以根据接口语义调整为更明确的命名,比如FriendsSet(对应全量设置操作)和FriendsAddedRemoved(对应明细变更),但现有命名已经足够直观。
内容的提问来源于stack exchange,提问作者GomalId
相关产品推荐
相关产品推荐

