使用redis的bitmap实现用户点赞功能

最近有一个需求,和新浪微博的评论很类似,是一个话题可以被评论,然后每个评论下都可以被回复,每个回复都有自己的回复数量,评论有评论的点赞数和回复数量,具体的方案如下:

使用redis的bitmap实现用户点赞功能_第1张图片

对于点赞这样的功能,操作非常的频繁,如果单纯的考虑数据库肯定是最low的方式。

还有需要考虑的,哪个用户点赞了,对哪个评论点赞了,这两点非常重要。需要维护的数据用户的id,评论的id,以及点赞的结果。

这里我采用了redis的bitmap数据结构。

这里简单介绍一下这个数据结构的常用命令,具体的原理暂时不做介绍。

几个常见的命令:

  setbit,getbit,bitcount

比如我实现id为100的用户对id为1000的评论点了赞,可以这么写

setbit 1000 100 1

获取id为100的用户对1000的评论是否点赞

getbit 1000 100  返回结果为 1

setbit key offsect value 

key是需要存储数据的key,本次设计key为评论内容的id

                                  offsect是偏移量,即我们关系的用户对评论的唯一性操作,即用户的id

                                     value 是最终是否存在这个value只能是0,1

有意思的是这个值可以一直赋值,比如第一次执行命令setbit 1000  100 1

再次执行setbit 1000  100 1 那么他的值就会变为0。这里正好应用这个特性实现判断用户是否点赞,如果点赞再次执行这个命令,用户就会取消点赞。

下面是StringredisTemplate客户端对上面几条命令的封装

//bitmap操作
    /**
     * setbit 设置一个值
     *
     * @param key
     * @param offset
     * @param value
     */
    public void setBit(String key, Long offset, Boolean value) {
        if (StringUtils.isBlank(key)) {
            throw new IllegalArgumentException("redis key is null");
        }
        redisTemplate.execute((RedisCallback) con -> con.setBit(key.getBytes(),offset , value));
    }

    /**
     * getBit
     * 获取指定offset的值
     *
     * @param key
     * @param offset
     * @return
     */

    public Boolean getBit(String key, Integer offset) {
        if (StringUtils.isBlank(key)) {
            throw new IllegalArgumentException("redis key is null");
        }
        return redisTemplate.execute((RedisCallback) con -> con.getBit(key.getBytes(), offset));

    }

    /**
     * bitcount
     * @param key
     * @return
     */
    public Integer bitCount(String key) {
        return redisTemplate.execute((RedisCallback) con -> con.bitCount(key.getBytes())).intValue();
    }

    public Long bitOp(RedisStringCommands.BitOperation op, String saveKey, String... desKey) {
        byte[][] bytes = new byte[desKey.length][];
        for (int i = 0; i < desKey.length; i++) {
            bytes[i] = desKey[i].getBytes();
        }
        return redisTemplate.execute((RedisCallback) con -> con.bitOp(op, saveKey.getBytes(), bytes));
    }

 

最后写写一个定时每天凌晨同步这些点赞数,评论数到咱们的mysql数据库就可以。这样就实现了一个点赞,取消点赞功能。

总结如下:

点赞,取消点赞

使用redis的bitmap实现用户点赞功能_第2张图片

这里还有一个是对用户回复的统计,由于需要统计每条回复被多少人回复了,这里我采用看传统redis,key,v结构

使用redis的incr原子特性结合每个回复内容的id使用进行统计累加

当用户回复了某个回复就会+1,这incr不会存在并发的问题,这是redis的原子操作命令。

使用redis的bitmap实现用户点赞功能_第3张图片

上面便是我使用redis对点赞以及评论功能的总结。over,下班,回家。

源码在我的资源里可以看到,需要的自行下载。

你可能感兴趣的:(redis)