服务器测评网
我们一直在努力

Java点赞功能怎么实现?高并发下Redis+MySQL优化方案

点赞功能作为社交、电商、内容平台等场景的核心交互模块,其实现需兼顾数据一致性、性能与并发安全性,本文将从基础设计到技术实现,详细拆解Java环境下的点赞功能开发逻辑,涵盖数据库设计、缓存策略、业务逻辑优化等关键环节。

Java点赞功能怎么实现?高并发下Redis+MySQL优化方案

基础需求与业务场景

点赞功能的核心需求包括:用户对目标对象(如文章、评论、商品)进行点赞/取消点赞操作,实时展示点赞数量,并支持查询用户点赞状态,常见业务场景中,需区分“普通点赞”与“点赞+踩”两种模式,本文以“普通点赞”为例展开,后者可扩展为双字段存储。

关键业务规则包括:

  • 唯一性约束:同一用户对同一目标只能点赞一次,取消后可再次点赞;
  • 实时性:点赞数量需即时更新,用户操作后能快速反馈;
  • 数据一致性:缓存与数据库数据需同步,避免脏读或漏写。

数据库与缓存设计

数据库设计

点赞数据需持久化存储,核心表结构设计如下(以MySQL为例):

CREATE TABLE `user_like` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) NOT NULL COMMENT '用户ID',
  `target_id` bigint(20) NOT NULL COMMENT '目标对象ID(如文章ID)',
  `target_type` tinyint(4) NOT NULL COMMENT '目标类型(1:文章, 2:评论)',
  `like_status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '点赞状态(1:点赞,0:取消)',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_user_target` (`user_id`, `target_id`, `target_type`) COMMENT '用户-目标唯一约束'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

设计要点

  • 联合唯一索引确保用户对同一目标只能有一条记录,避免重复点赞;
  • target_type字段支持多类型目标扩展,如文章、评论、商品等;
  • like_status字段标识点赞状态,支持取消操作(逻辑删除)。

缓存设计

点赞操作高频读写,需引入缓存(如Redis)提升性能,缓存设计需满足:

  • 点赞状态缓存:使用Hash结构存储用户对目标的点赞状态,Key格式为like_status:{target_type}:{target_id},Field为user_id,Value为1(点赞)或0(取消);
  • 点赞数量缓存:使用String结构存储目标点赞数,Key格式为like_count:{target_type}:{target_id},Value为数量值,初始为0。

缓存优势:减少数据库访问压力,响应速度提升至毫秒级;支持原子操作,避免并发问题。

Java点赞功能怎么实现?高并发下Redis+MySQL优化方案

核心业务逻辑实现

点赞/取消点赞流程

以“点赞”操作为例,核心逻辑如下(伪代码):

public void like(Long userId, Long targetId, Integer targetType) {
    // 1. 检查缓存中的点赞状态
    String statusKey = "like_status:" + targetType + ":" + targetId;
    String countKey = "like_count:" + targetType + ":" + targetId;
    // 2. 使用Redis原子操作(Lua脚本保证原子性)
    String luaScript = 
        "local status = redis.call('HGET', KEYS[1], ARGV[1]) " +
        "if status == 1 then " +
        "   return 0 " +  // 已点赞,不做操作
        "else " +
        "   redis.call('HSET', KEYS[1], ARGV[1], 1) " +
        "   redis.call('INCR', KEYS[2]) " +
        "   return 1 " +  // 点赞成功
        "end";
    // 3. 执行Lua脚本,更新缓存
    Long result = redisTemplate.execute(
        new DefaultRedisScript<>(luaScript, Long.class),
        Arrays.asList(statusKey, countKey),
        userId.toString()
    );
    // 4. 若缓存操作成功,异步更新数据库
    if (result == 1) {
        asyncUpdateDatabase(userId, targetId, targetType, 1);
    }
}

关键点

  • 使用Redis Lua脚本保证“检查-设置”操作的原子性,避免并发竞态;
  • 缓存优先策略,先更新缓存再异步落库,提升响应速度;
  • 取消点赞逻辑类似,将HSET改为HDELINCR改为DECR

查询点赞状态与数量

  • 查询用户点赞状态:直接从Redis Hash中获取,若缓存未命中则查询数据库并回填缓存;
  • 查询点赞数量:优先从Redis String获取,若缓存未命中则查询数据库并初始化缓存。

接口与交互设计

对外提供RESTful API,核心接口如下:

  • 点赞/取消点赞POST /api/like,参数:userId(用户ID)、targetId(目标ID)、targetType(目标类型)、actionlike/unlike);
  • 查询点赞状态GET /api/like/status?userId={userId}&targetIds={ids}&targetType={type},返回Map<targetId, Boolean>
  • 查询点赞数量GET /api/like/count?targetIds={ids}&targetType={type},返回Map<targetId, Integer>

接口规范:统一返回格式(如{code: 200, data: {...}}),参数校验(非空、类型校验),异常处理(如重复点赞、目标不存在)。

性能与并发优化

并发处理

  • 分布式锁:在分布式环境下,使用Redis分布式锁(如Redission)控制并发点赞,避免同一用户短时间内重复操作;
  • 限流机制:基于Redis滑动窗口算法限制用户点赞频率(如每分钟最多10次),防止恶意刷赞。

数据一致性

  • 缓存与数据库同步:采用“先更新缓存,再异步更新数据库”策略,通过消息队列(如RabbitMQ)异步落库,避免数据库压力过大;
  • 缓存重建:当数据库更新失败时,通过定时任务定期校验缓存与数据库一致性,修复异常数据。

批量查询优化

对于批量查询点赞状态(如获取某篇文章下100个用户的点赞情况),使用Redis HMGET命令一次性获取多个Field的值,减少网络IO次数。

扩展性与场景适配

多类型目标支持

通过target_type字段区分不同目标类型,如文章(1)、评论(2)、商品(3),无需为每种类型建表,提升扩展性。

Java点赞功能怎么实现?高并发下Redis+MySQL优化方案

分库分表

当数据量过大(如日点赞千万级),可按target_idtarget_type进行分表,分散数据库压力。

点赞日志记录

单独建表存储点赞操作日志(含用户ID、目标ID、操作时间、IP等),用于用户行为分析或审计。

Java点赞功能的实现需从数据层、缓存层、业务层协同设计:数据库保证持久化与一致性,缓存提升性能,业务逻辑处理核心规则与并发场景,实际开发中,需根据业务规模选择合适的技术方案(如是否引入分布式锁、消息队列),并通过监控(如Prometheus)实时跟踪点赞系统的性能指标,确保稳定运行。

赞(0)
未经允许不得转载:好主机测评网 » Java点赞功能怎么实现?高并发下Redis+MySQL优化方案