疑问
当看到这个标题,可能会有些大佬有点模糊,因为为什么不用数据库去实现,而用redis来实现这个功能,那我们可以一起来思考一下。
为什么实现redis,而不用数据库
- 先从安全方面来讲,如果使用数据库,假如用户频繁点赞,取消点赞这些操作的话,那么会给数据库造成压力,如果使用缓存的话,那么压力不会那么大。
- 从效率方面考虑,redis数据存在与内存,所以速度收到内存影响,数据库存在与硬盘,速度没redis快。
- 从功能方面考虑,redis只支持几种数据结构,没用数据库支持的多。
Redis几种数据结构的适用场景
- List: 双向列表,适用于最新列表,关注列表;
- Set: 适用于无顺序的集合,点赞点踩,抽奖,已读,共同好友;
- SortedSet : 具有排序加成功能,适用于排行榜,优先队列的实现;
- Hash:对象属性,不定长属性数;
- 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.上述没问题,但是还是要考虑把缓存的数据存入数据库,可以使用定时任务去处理,大佬们如果还有其他好的方案,也可以提出。