点赞收藏功能通过缓存、异步处理和分库分表实现高效性,利用Redis缓存热点数据与用户行为,结合消息队列异步更新数据库,保证快速响应与数据最终一致性,并通过item_type支持多内容类型。
点赞、收藏功能的核心在于快速响应、数据一致性和可扩展性。实现高效,意味着我们要在用户体验和系统负载之间找到平衡。
解决方案
数据模型设计:
user_id,
item_id,
item_type,
created_at。
item_type用于区分文章、评论等不同类型的点赞对象。联合索引
(item_id, item_type)和
(user_id, item_id, item_type),前者用于统计,后者用于判断用户是否已点赞。
user_id,
item_id,
item_type,
created_at。结构与点赞表类似。
item_id,
item_type,
likes_count,
collections_count。用于存储点赞和收藏的总数,避免频繁的 COUNT 查询。
缓存策略:
ItemCounts表中的数据。更新点赞/收藏时,先更新缓存,再异步更新数据库。
item_id。在用户请求点赞/收藏时,先检查缓存,减少数据库查询。
异步处理:
数据库优化:
user_id或
item_id进行 Hash 分片。
API 设计:
如何处理高并发场景下的点赞风暴?
点赞风暴是指短时间内大量用户同时点赞某个内容,导致系统负载过高。
限流: 使用令牌桶或漏桶算法限制单位时间内请求的数量,防止系统被瞬间流量冲垮。可以在 Nginx 或 API 网关层进行限流。
熔断: 当某个服务出现故障时,自动熔断该服务,防止雪崩效应。可以使用 Hystrix 或 Resilience4j 等熔断器。
降级: 在系统负载过高时,可以采取降级措施,例如:
ItemCounts表,改为定时批量更新。
预热: 提前预知可能出现点赞风暴的内容,提前将相关数据加载到缓存中,提高响应速度。
如何保证点赞和收藏数据的一致性?
数据一致性是点赞/收藏功能的关键。以下是一些保证数据一致性的方法:
事务: 在更新数据库时,使用事务保证 ACID 特性。如果更新失败,可以回滚事务,保证数据的一致性。
最终一致性: 由于缓存和数据库之间存在延迟,因此只能保证最终一致性。可以通过以下方法尽量减少延迟:

补偿机制: 如果异步更新数据库失败,可以通过补偿机制重试。可以使用消息队列的重试机制或自定义重试逻辑。
点赞和收藏功能如何支持不同的内容类型?
通过
item_type字段来区分不同的内容类型(文章、评论、视频等)。
统一接口: 点赞/收藏接口接收
item_id和
item_type作为参数,根据
item_type找到对应的数据表进行操作。
策略模式: 使用策略模式,根据不同的
item_type选择不同的处理策略。例如,文章的点赞逻辑和评论的点赞逻辑可能不同。
元数据: 可以为每种
item_type定义元数据,例如:
通过元数据,可以灵活地支持新的内容类型,而无需修改核心代码。
# 示例代码:使用策略模式处理不同类型的点赞
class LikeStrategy:
def like(self, user_id, item_id):
raise NotImplementedError
class ArticleLikeStrategy(LikeStrategy):
def like(self, user_id, item_id):
# 文章点赞逻辑
print(f"用户 {user_id} 点赞了文章 {item_id}")
class CommentLikeStrategy(LikeStrategy):
def like(self, user_id, item_id):
# 评论点赞逻辑
print(f"用户 {user_id} 点赞了评论 {item_id}")
class LikeContext:
def __init__(self, strategy: LikeStrategy):
self.strategy = strategy
def set_strategy(self, strategy: LikeStrategy):
self.strategy = strategy
def like(self, user_id, item_id):
self.strategy.like(user_id, item_id)
# 使用示例
article_strategy = ArticleLikeStrategy()
comment_strategy = CommentLikeStrategy()
context = LikeContext(article_strategy)
context.like(123, 456) # 用户 123 点赞了文章 456
context.set_strategy(comment_strategy)
context.like(123, 789) # 用户 123 点赞了评论 789