title: 分布式事件在点赞功能中的实现
date: 2025/04/27 13:01:10
updated: 2025/04/27 13:01:10
author: cmdragon
excerpt:
分布式事件在点赞功能中面临原子性、数据一致性和失败补偿的挑衅。Tortoise-ORM提供基础事件和装饰器事件两种管理方式,确保数据一致性。点赞功能实现需防重复点赞和事件处理,采用唯一约束防止重复。跨服务事件处理使用Saga模式,按反向序次执行补偿操纵确保最终一致性。常见报错包括事件超时、唯一约束辩论和请求参数校验失败,需优化事件操纵、使用upsert和详细响应模型解决。
categories:
tags:
- 分布式事件
- 微服务架构
- Tortoise-ORM
- 点赞功能
- Saga模式
- 事件管理
- 数据一致性
扫描二维码关注大概微信搜一搜:编程智域 前端至全栈交换与成长
探索数千个预构建的 AI 应用,开启你的下一个巨大创意:https://tools.cmdragon.cn/
第一章:分布式事件在点赞功能中的应用
1.1 分布式事件焦点原理
在微服务架构中,一个业务操纵可能涉及多个独立服务的数据修改。传统数据库事件的ACID特性(原子性、一致性、隔离性、长期性)在分布式环境中面临挑衅:
- 原子性困境:跨服务的操纵无法使用单一数据库事件保证
- 数据一致性:各服务数据库独立,无法通过锁机制实现强一致性
- 失败补偿:部分操纵乐成后出现非常需要回滚的复杂处理
以点赞功能为例,典型业务场景包罗:
- 用户服务(扣除点赞次数) → 文章服务(增加点赞数) → 通知服务(发送消息)
复制代码 1.2 Tortoise-ORM事件配置
Tortoise-ORM提供两种事件管理方式:
基础事件模式:
- async with in_transaction() as conn:
- await User.filter(id=user_id).update(likes=F('likes') + 1)
- await Article.filter(id=article_id).update(likes=F('likes') + 1)
复制代码 装饰器事件模式:
- @atomic()
- async def like_article(user_id: int, article_id: int):
- user = await User.get(id=user_id)
- article = await Article.get(id=article_id)
- await Like.create(user=user, article=article)
复制代码 1.3 点赞功能实现方案
完备实现包罗防重复点赞和事件处理:
- # 数据库模型
- class Like(Model):
- id = fields.IntField(pk=True)
- user = fields.ForeignKeyField('models.User')
- article = fields.ForeignKeyField('models.Article')
- created_at = fields.DatetimeField(auto_now_add=True)
- class Meta:
- unique_together = (('user', 'article'),) # 唯一约束防重复
- # 业务逻辑
- async def toggle_like(user_id: int, article_id: int):
- try:
- async with in_transaction():
- # 检查是否已点赞
- exists = await Like.exists(user_id=user_id, article_id=article_id)
- if exists:
- # 取消点赞
- await Like.filter(user_id=user_id, article_id=article_id).delete()
- delta = -1
- else:
- # 新增点赞
- await Like.create(user_id=user_id, article_id=article_id)
- delta = 1
- # 更新统计数
- await User.filter(id=user_id).update(likes_count=F('likes_count') + delta)
- await Article.filter(id=article_id).update(likes_count=F('likes_count') + delta)
- return {"status": "success", "action": "unlike" if exists else "like"}
- except IntegrityError:
- raise HTTPException(status_code=400, detail="操作冲突,请重试")
复制代码 1.4 跨服务事件处理
当涉及多个微服务时,采用Saga事件模式实现最终一致性:
- # Saga协调器示例
- class LikeSaga:
- def __init__(self):
- self.compensation_actions = []
- async def execute(self):
- try:
- # 阶段1:预扣点赞次数
- await user_service.decrement_quota(user_id)
- self.compensation_actions.append(
- lambda: user_service.increment_quota(user_id)
- )
- # 阶段2:增加文章点赞
- await article_service.increment_likes(article_id)
- self.compensation_actions.append(
- lambda: article_service.decrement_likes(article_id)
- )
- # 阶段3:发送通知
- await notification_service.send_like_notice(user_id, article_id)
- except Exception as e:
- # 执行补偿操作
- for action in reversed(self.compensation_actions):
- await action()
- raise
复制代码 课后Quiz
Q1:为什么在点赞功能中需要唯一约束?
A. 提高查询速度
B. 防止用户重复点赞
C. 减少数据库存储空间
D. 方便统计用户数据
正确答案:B
剖析:唯一约束确保(user_id, article_id)组合的唯一性,从数据库层面防止重复点赞,比应用层检查更可靠。
Q2:Saga模式中的补偿操纵应该按什么序次执行?
A. 任意序次
B. 正向序次
C. 反向序次
D. 随机序次
正确答案:C
剖析:补偿操纵需要按照与业务操纵相反的序次执行,比方先撤销最后完成的操纵。
常见报错解决
错误1:TransactionManagementError - 事件超时
原因分析:
- 长时间未提交的事件导致锁等候超时
- 复杂事件处理时间凌驾数据库配置的超时阈值
解决方案:
- 优化事件内的操纵,减少不须要的数据库交互
- 在事件开始时设置合理超时时间:
- async with in_transaction(timeout=30) as conn: # 30秒超时
- # 业务操作
复制代码 错误2:IntegrityError - 唯一约束辩论
原因分析:
解决方案:
- 在前端添加防重提交机制
- 在后端使用upsert操纵:
- await Like.update_or_create(
- user_id=user_id,
- article_id=article_id,
- defaults={'created_at': datetime.now()}
- )
复制代码 错误3:ValidationError - 请求参数校验失败
原因分析:
- 客户端传递的参数不符合Pydantic模型要求
- 数值型参数传递了字符串类型
解决方案:
- 检查请求体是否符合接口文档要求
- 在路由中添加详细的响应模型:
- @app.post("/likes", response_model=LikeResponse, responses={
- 422: {"model": ValidationErrorResponse}
- })
复制代码 余下文章内容请点击跳转至 个人博客页面 大概 扫码关注大概微信搜一搜:编程智域 前端至全栈交换与成长,阅读完备的文章:分布式事件在点赞功能中的实现 | cmdragon's Blog
往期文章归档:
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! 更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |