首先我们需要分析下朋友圈点赞需要有哪些功能:
- 支持点赞数量的查看
- 支持点赞和取消点赞
- 支持查看哪些人点过赞
- 支持查看点赞的顺序
那么基于以上需求,大致的结构如下:
在数据结构上,key就是这个具体的朋友圈ID,ZSet的Value表示点赞用户的ID,score表示点赞时间的时间戳,这样可以方便地按时间顺序查询点赞信息,并支持对点赞进行去重,话不多说,接下来就是实战。
- 使用字符串存储每篇朋友圈的ID,作为有序集合的key
- 使用zset存储每篇朋友圈的点赞用户信息,其中value为点赞用户的ID,score为点赞时间的时间戳。
- 点赞操作:将用户的ID添加到zset中,score为当前时间戳。如果用户已经点过赞,则更新其点赞时间戳。
- 取消点赞操作:将用户的ID从有序集合中删除。
- 查询点赞信息:使用有序集合的ZREVRANGEBYSCORE命令,按照score(时间戳)逆序返回zset的value,即为点赞用户的ID。
以下是代码实现:
import redis.clients.jedis.Jedis;
import redis.clients.jedis.ZParams;
import java.util.List;
import java.util.stream.Collectors;
public class LikeDemo {
public static final String LIKE_PREFIX = "like:";
public static final String USER_PREFIX = "user:";
/**
* 点赞
*
* @param postId 文章id
* @param userId 用户id
* @param jedis
*/
public static void likePost(String postId, String userId, Jedis jedis) {
String key = LIKE_PREFIX + postId;
long now = System.currentTimeMillis();
//将用户id及当前时间戳放入有序集合
jedis.zadd(key, now, userId);
}
/**
* 取消点赞
*
* @param postId 文章id
* @param userId 用户id
* @param jedis
*/
public static void unLikePost(String postId, String userId, Jedis jedis) {
String key = LIKE_PREFIX + postId;
//将用户id从有序集合中移除
jedis.zrem(key, userId);
}
/**
* 查看点赞列表
*
* @param postId 文章id
* @param jedis
* @return
*/
public List<String> getLikes(String postId, Jedis jedis) {
String key = LIKE_PREFIX + postId;
ZParams zParams = new ZParams().asc();
return jedis.zrangeByScoreWithScores(key, "+inf", "-inf", 0, -1, zParams)
.stream()
.map(t -> {
String userId = t.getElement();
return userId;
}).collect(Collectors.toList());
}
}
其中,likePost方法使用了Redis事物机制,确保添加点赞信息和设置过期时间是原子操作。getLikes方法使用了有序集合的zrangeByScoreWithScores命令,按照分支返回有序集合的成员。