Skip to content

面试速答(先看这里)

**一句话结论:**在数据结构上,我们可以采用ZSet来实现,KEY就是这个具体的朋友圈的ID,ZSET的value表示点赞用户的ID,score表示点赞时间的时间戳。

60秒标准回答:

首先我们需要分析下朋友圈点赞需要有哪些功能,首先记录某个朋友圈的点赞数量,并且支持点赞数数量的查看,支持点赞和取消点赞操作。并且支持查看哪些人点过赞,并且点赞的顺序是可以看得到的

那么,基于以上信息,我们可以这样实现

在数据结构上,我们可以采用ZSet来实现,KEY就是这个具体的朋友圈的ID,ZSET的value表示点赞用户的ID,score表示点赞时间的时间戳。这样可以方便地按照时间顺序查询点赞信息,并支持对点赞进行去重

**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点

回答主线:

  • **要点1:**首先我们需要分析下朋友圈点赞需要有哪些功能,首先记录某个朋友圈的点赞数量,并且支持点赞数数量的查看,支持点赞和取消点赞操作。
  • **要点2:**那么,基于以上信息,我们可以这样实现:
  • **要点3:**在上述代码中,likePost方法用于点赞,unlikePost方法用于取消点赞,getLikes方法用于查询点赞信息。

**记忆锚点:**score → value → zset → KEY → ZREVRANGEBYSCORE → unlikePost

加分表达:

  • 如果用户已经点过赞,则更新其点赞时间戳。

追问准备:

  • 围绕「score」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「value」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「zset」:底层原理是什么?使用时有哪些边界和常见坑?
  • 如果线上出现异常,你会如何定位、验证并规避?

典型回答 ​

首先我们需要分析下朋友圈点赞需要有哪些功能,首先记录某个朋友圈的点赞数量,并且支持点赞数数量的查看,支持点赞和取消点赞操作。并且支持查看哪些人点过赞,并且点赞的顺序是可以看得到的。

image.png

那么,基于以上信息,我们可以这样实现:

在数据结构上,我们可以采用ZSet来实现,KEY就是这个具体的朋友圈的ID,ZSET的value表示点赞用户的ID,score表示点赞时间的时间戳。这样可以方便地按照时间顺序查询点赞信息,并支持对点赞进行去重,

  1. 使用字符串存储每篇朋友圈的ID,作为有序集合的KEY。
  2. 使用zset存储每篇朋友圈的点赞用户信息,其中value为点赞用户的ID,score为点赞时间的时间戳。
  3. 点赞操作:将用户的ID添加到zset中,score为当前时间戳。如果用户已经点过赞,则更新其点赞时间戳。
  4. 取消点赞操作:将用户的ID从有序集合中删除。
  5. 查询点赞信息:使用有序集合的ZREVRANGEBYSCORE命令,按照score(即时间戳)逆序返回zset的value,即为点赞用户的ID。

以下是代码实现:

plain
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
import redis.clients.jedis.ZParams;
/**
* @author Hollis
**/
public class RedisLikeDemo {
    private static final String LIKE_PREFIX = "like:";
    private static final String USER_PREFIX = "user:";

  	//点赞
    public static void likePost(String postId, String userId, Jedis jedis) {
        String key = LIKE_PREFIX + postId;
        Long now = System.currentTimeMillis();
        jedis.zadd(key, now.doubleValue(), userId);// 将用户ID及当前时间戳加入有序集合
    }

  	//取消点赞
    public static void unlikePost(String postId, String userId, Jedis jedis) {
        String key = LIKE_PREFIX + postId;
        jedis.zrem(key, userId);// 将用户ID从有序集合中移除
    }

  	//查看点赞列表
    public List<String> getLikes(String postId, Jedis jedis) {
        String key = LIKE_PREFIX + postId;
        ZParams zParams = new ZParams().desc();
        return jedis.zrangeByScoreWithScores(key, "+inf", "-inf", 0, -1, zParams)
                .stream()
                .map(tuple -> {
                    String userId = tuple.getElement();
                    return userId;
                }).collect(Collectors.toList());
    }
}

在上述代码中,likePost方法用于点赞,unlikePost方法用于取消点赞,getLikes方法用于查询点赞信息。