疑问

当看到这个标题,可能会有些大佬有点模糊,因为为什么不用数据库去实现,而用redis来实现这个功能,那我们可以一起来思考一下。

为什么实现redis,而不用数据库

  1. 先从安全方面来讲,如果使用数据库,假如用户频繁点赞,取消点赞这些操作的话,那么会给数据库造成压力,如果使用缓存的话,那么压力不会那么大。
  2. 从效率方面考虑,redis数据存在与内存,所以速度收到内存影响,数据库存在与硬盘,速度没redis快。
  3. 从功能方面考虑,redis只支持几种数据结构,没用数据库支持的多。

Redis几种数据结构的适用场景

  1. List: 双向列表,适用于最新列表,关注列表;
  2. Set: 适用于无顺序的集合,点赞点踩,抽奖,已读,共同好友;
  3. SortedSet : 具有排序加成功能,适用于排行榜,优先队列的实现;
  4. Hash:对象属性,不定长属性数;
  5. KV : 单一数值,适用于验证码,缓存等实现。

代码实现

1.第一步,引入依赖

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

2.使用redis工具类

@Component
public class RedisUtil<T> {

    @Autowired
    private RedisTemplate redisTemplate;
    
    /**
     * 当key值不存在时新增缓存返回true,否则返回false
     * @param key
     * @param value
     * @return
     */
    public boolean setNx(String key, String value) {
        return redisTemplate.opsForValue().setIfAbsent(key,value);
    }

    /**
     * 向redis中set集合添加值,点赞
     * @param key
     * @param value
     * @return
     */
    public void sAdd(String key,String value) {
        redisTemplate.opsForSet().add(key,value);
    }

    /**
     * 向redis中set集合移除,取消点赞
     * @param key
     * @param value
     * @return
     */
    public Long srem(String key,String value) {
       return redisTemplate.opsForSet().remove(key,value);
    }

    /**
     * 判断key,value是否是集中值
     * @param key
     * @param value
     * @return
     */
    public boolean isMember(String key,String value) {
        return redisTemplate.opsForSet().isMember(key,value);
    }

    /**
     * 获取集合大小
     * @param key
     * @return
     */
    public Long size(String key) {
        return redisTemplate.opsForSet().size(key);
    }

    /**
     * 获取集合里所有数据
     * @param key
     * @return
     */
    public Set<String> sMembers(String key) {
        Set<String> members = redisTemplate.opsForSet().members(key);
        return members;
    }
}

3.控制层

@RestController
public class RedisController {
    @Autowired
    private RedisUtil redisUtil;

    @GetMapping(value = "/giveLike/{name}")
    @ApiOperation(value = "用户点赞接口", notes = "用户点赞接口")
    public RestResponse giveLike(@PathVariable String name) {
        redisUtil.sAdd("like:user",name);
        return ResultGenerator.genSuccessResult("点赞成功!");
    }

    @GetMapping(value = "/giveCancelLike/{name}")
    @ApiOperation(value = "用户取消点赞接口", notes = "用户取消点赞接口")
    public RestResponse giveCancelLike(@PathVariable String name) {
        redisUtil.srem("like:user",name);
        return ResultGenerator.genSuccessResult("取消成功!");
    }

    @GetMapping(value = "/isGiveLike/{name}")
    @ApiOperation(value = "判断用户是否点赞", notes = "判断用户是否点赞")
    public RestResponse isGiveLike(@PathVariable String name) {
        boolean member = redisUtil.isMember("like:user", name);
        if (member) {
            return ResultGenerator.genSuccessResult("已点赞");
        }
        return ResultGenerator.genSuccessResult("未点赞");
    }

    @GetMapping(value = "/getGiveLikeList")
    @ApiOperation(value = "获取点赞列表", notes = "获取点赞列表")
    public RestResponse getGiveLikeList() {
        Set<String> set = redisUtil.sMembers("like:user");
        return ResultGenerator.genSuccessResult(set);
    }

    @GetMapping(value = "/getGiveLikeSize")
    @ApiOperation(value = "获取点赞人数", notes = "获取点赞人数")
    public RestResponse getGiveLikeSize() {
        Long aLong = redisUtil.sCard("like:user");
        return ResultGenerator.genSuccessResult(aLong);
    }
}

4.这里对like:user这个key进行操作。

  • 调用点赞接口
    在这里插入图片描述
  • 查看缓存
    在这里插入图片描述
  • 取消点赞
    在这里插入图片描述
    查看缓存,已经成功删除
    在这里插入图片描述
    -查看点赞列表
    在这里插入图片描述

5.上述没问题,但是还是要考虑把缓存的数据存入数据库,可以使用定时任务去处理,大佬们如果还有其他好的方案,也可以提出。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐