redis集群实现文章点赞投票

import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.ZParams;

import java.util.*;

@RestController
@RequestMapping("/article")
public class ArticleController {
    @Autowired
    private JedisCluster jedisCluster;

    private static final int VOTE_SCORE = 432;
    private static final int ARTICLES_PER_PAGE = 25;
    private static final String prefix = "luffi:lbl";
    private static final String KEY_SPLIT = ":"; //用于隔开缓存前缀与缓存键值

    @RequestMapping("/add")
    public String postArticle(String title, String link, String user, String group) {
        //获取id
        String articleid = jedisCluster.incr("articleid").toString();
        //组装文章信息
        long now = System.currentTimeMillis();
        Map<String, String> articleinfo = new HashMap<>();
        articleinfo.put("title", title);
        articleinfo.put("link", link);
        articleinfo.put("user", user);
        articleinfo.put("time", now + "");
        articleinfo.put("vote", "1");
        articleinfo.put("group", group);
        jedisCluster.hmset("article:" + articleid, articleinfo);
        //将文章放入时间排列表中
        jedisCluster.zadd("{" + prefix + KEY_SPLIT + "}" + "time", Double.parseDouble(now + ""), articleid);
        //将文章放入分数排列表中
        jedisCluster.zadd("{" + prefix + KEY_SPLIT + "}" + "score", Double.parseDouble(now + VOTE_SCORE + ""), articleid);
        //将文章id放入指定分类中
        jedisCluster.sadd("{" + prefix + KEY_SPLIT + "}" + "group_" + group, articleid);
        return articleid;
    }

    /**
     * 获取文章列表
     *
     * @param pageNo
     * @param key
     * @return
     */
    @RequestMapping("/articles")
    public String getArticlePage(int pageNo, String key) {

        if (pageNo <= 0) {
            pageNo = 1;
        }

        int start = (pageNo - 1) * ARTICLES_PER_PAGE;
        int end = start + ARTICLES_PER_PAGE - 1;
        Set<String> zrange = jedisCluster.zrevrange(key, start, end);
        List<Map<String, String>> list = new LinkedList<>();
        zrange.stream().forEach(articltid -> {
            Map<String, String> article = jedisCluster.hgetAll("article:" + articltid);
            list.add(article);
        });
        return JSON.toJSONString(list);
    }

    /**
     * 对分类进行排序缓存
     *
     * @param group  分类名称
     * @param sort   score-按热度排序 time-按时间排序
     * @param pageNo 页数
     * @return
     */
    @RequestMapping("/groupsort")
    public String groupsort(String group, String sort, int pageNo) {

        if (pageNo <= 0) {
            pageNo = 1;
        }
        String key = "{" + prefix + KEY_SPLIT + "}" + sort + group;
        if (!jedisCluster.exists(key)) {
            ZParams zParams = new ZParams().aggregate(ZParams.Aggregate.MAX);
            jedisCluster.zinterstore(key, zParams, "{" + prefix + KEY_SPLIT + "}" + group, "{" + prefix + KEY_SPLIT + "}" + sort);
            jedisCluster.expire(key,10);
        }
        return getArticlePage(pageNo, key);
    }
}


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.JedisCluster;

/**
 * 点赞投票
 * 为了产生一个能够随着时间流逝而不断减少的评分,程序需要根据文章的发布时间和当前时间来计算文章的评分,
 * 具体的计算方法为:将文章得到的支持票数量乘以一个常量,然后加上文章的发布时间,得出的结果就是文章的评分。
 * 我们使用从UTC时区1970年1月1日到现在为止经过的秒数来计算文章的评分,这个值通常被称为Unix时间。
 * 之所以选择使用Uni x时间,是因为在所有能够运行Redis的平台上面,使用编程语言获取这个值都是一件非常简单的事情。
 * 另外,计算评分时与支持票数量相乘的常量为432,这个常量是通过将一天的秒数(86 400)除以文章展示一天所需的支持票数量(200)得出的:
 * 文章每获得一张支持票,程序就需要将文章的评分增加432分。
 */
@RestController
@RequestMapping("/vote")
public class VoteController {
    private static final int ONE_WEEK_IN_SECONDS = 7 * 86400 * 1000;
    private static final int VOTE_SCORE = 432 * 1000;
    private static final String prefix = "luffi:lbl";
    private static final String KEY_SPLIT = ":"; //用于隔开缓存前缀与缓存键值
    @Autowired
    private JedisCluster jedisCluster;

    /**
     * 点赞支持
     * @param articleid
     * @param user
     * @return
     */
    @RequestMapping("incr")
    public String vote(String articleid, String user) {
        long l = System.currentTimeMillis() - ONE_WEEK_IN_SECONDS;
        if (jedisCluster.zscore("{" + prefix + KEY_SPLIT + "}" + "time", articleid) < l)
            return "文章过了点赞时间";
        //将点赞人放入点赞队列
        Long sadd = jedisCluster.sadd("{" + prefix + KEY_SPLIT + "}" + "vote_user:" + articleid, user);
        if (sadd <= 0) {
            return "您已经点过赞!";
        }
        Long smove = jedisCluster.smove("{" + prefix + KEY_SPLIT + "}" + "opposition_user:" + articleid,"{" + prefix + KEY_SPLIT + "}" + "vote_user:" + articleid,  user);
        if (smove > 0) {
            jedisCluster.hincrBy("article:" + articleid, "vote", 2);
            jedisCluster.zincrby("{" + prefix + KEY_SPLIT + "}" + "score", VOTE_SCORE * 2, articleid);
        }else {
            //没有投过支持票
            jedisCluster.hincrBy("article:" + articleid, "vote", 1);
            jedisCluster.zincrby("{" + prefix + KEY_SPLIT + "}" + "score", VOTE_SCORE , articleid);
        }
        return "success";
    }

    /**
     * 投反对票
     *
     * @param articleid
     * @param user
     * @return
     */
    @RequestMapping("/decr")
    public String decr(String articleid, String user) {
        long l = System.currentTimeMillis() - ONE_WEEK_IN_SECONDS;
        if (jedisCluster.zscore("{" + prefix + KEY_SPLIT + "}" + "time", articleid) < l)
            return "文章过了点赞时间";
        Long sadd = jedisCluster.sadd("{" + prefix + KEY_SPLIT + "}" + "opposition_user:" + articleid, user);
        if (sadd < 0) {
            return "您已经投过反对票!";
        }
        //判断此人是否投过支持票,如果投过支持票直接将此人从该文章的支持列表中移动到反对列表中,并将文章减去双倍积分,如果此人没有投过支持票,则减去一倍的分数
        Long smove = jedisCluster.smove("{" + prefix + KEY_SPLIT + "}" + "vote_user:" + articleid, "{" + prefix + KEY_SPLIT + "}" + "opposition_user:" + articleid, user);
        if (smove > 0) {
            //投过支持票并且已经将此人移动到反对票李表中
            jedisCluster.hincrBy("article:" + articleid, "vote", -2);
            jedisCluster.zincrby("{" + prefix + KEY_SPLIT + "}" + "score", -VOTE_SCORE * 2, articleid);
        }else {
            //没有投过支持票
            jedisCluster.hincrBy("article:" + articleid, "vote", -1);
            jedisCluster.zincrby("{" + prefix + KEY_SPLIT + "}" + "score", -VOTE_SCORE , articleid);
        }
        return "success";
    }


}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值