参考《redis实战》

需要

1、文章信息包含:题目、内容、链接、公布工夫、公布人,公布后就给本人投一张票。
2、一个人只能给一篇文章投一张票。
3、文章只能七天内容许投票。
4、文章投票排名思考文章公布工夫以及投票数量,以公布工夫作为降序排序,如果投票数量为200,则工夫向前移一天。
5、文章排序包含公布工夫排序,投票得分排序

剖析

第一个需要

能够采纳散列来保留文章信息。存入信息用HMSET,取出对应字段信息用HMGET,取出key的所有信息用HGETALL,根本用法如下:

// 赋值local:0>hmset person:001 name '张三' age 18"OK"// 取对应key的某个属性值 local:0>hmget person:001 name1) "张三"// 取对应key的所有属性值local:0>hgetall person:0011) "name"2) "张三"3) "age"4) "18"

第二个需要

这边思考到不能反复的概念,在java里用set,redis也有汇合的概念。汇合简略的说,就是不能有反复的数据,根本用法如下:

// 赋值local:0>sadd name '张三'"1"// 赋值local:0>sadd name '李四'"1"// 赋值失败,返回0,因为曾经增加过local:0>sadd name '张三'"0"// 获取对应key的所有成员local:0>smembers name1) "张三"2) "李四"

第三个需要

有工夫管制需要,须要把文章id和公布工夫保存起来,思考到前面用工夫进行排序,所以用有序汇合。有序汇合和下面汇合不一样的是,多了一个分值的概念,能够通过分值进行排序等操作。七天后不能投票就能够通过这个分值来计算。

// 增加local:0>zadd score 88 '赵大'"1"// 增加local:0>zadd score 93 '熊二'"1"// 增加local:0>zadd score 92 '张三'"1"  // 增加local:0>zadd score 89 '李四'"1"// 增加local:0>zadd score 70 '王五'"1"// 反复增加失败返回0,local:0>zadd score 60 '王五'"0"// 分数加5,返回最终值local:0>zincrby score 5 '王五'"65"// 从低到高排序,取前四个local:0>zrange score 0 3 withscores1) "王五"2) "65"3) "赵大"4) "88"5) "李四"6) "89"7) "张三"8) "92"// 从高到低排序,取前四个local:0>zrevrange score 0 3 withscores1) "熊二"2) "93"3) "张三"4) "92"5) "李四"6) "89"7) "赵大"8) "88"// 获取分数值local:0>zscore score '张三'"92"

第四个需要

一天有84600秒,200票工夫向前挪动一天,则每票就是84600/200=432分。

第五个需要

投票要依据分数来排序,所以同需要三,用有序汇合。

实际

公布文章

private static final int ONE_WEEK_IN_SECONDS = 7 * 86400;private static final int VOTE_SCORE = 432;@Testpublic void postArticle() throws InterruptedException {    for (int i = 0; i < 5; i++) {        // 通过incre获取自增长主键        String articleId = String.valueOf(JedisUtils.incre("article:"));        // 定义主键        String article = "article:" + articleId;        long now = System.currentTimeMillis() / 1000;        String user = "公布人" + i;        // 设置文章        Map<String, String> articleMap = new HashMap<>();        articleMap.put("title", "文章题目" + i);        articleMap.put("content", "文章内容" + i);        articleMap.put("link", "文章链接" + i);        articleMap.put("user", user);        articleMap.put("now", String.valueOf(now));        // 记录投票数        articleMap.put("votes", "1");        // 记录投票人,避免反复投票,设置过期工夫        String voted = "voted:" + articleId;        JedisUtils.sadd(voted, user);        JedisUtils.expire(voted, ONE_WEEK_IN_SECONDS);        // 通过文章主键插入        JedisUtils.hmset(article, articleMap);        //须要工夫和分数排序        JedisUtils.zadd("score:", now + VOTE_SCORE, article);        JedisUtils.zadd("time:", now, article);        TimeUnit.SECONDS.sleep(1);    }}

投票

@Testpublic void voteArticle() {    for (int i = 1; i < 3; i++) {        String article = "article:" + i;        String voted = "voted:" + i;        System.out.println("投票前,第一篇文章和第二篇文章的投票数:");        System.out.println("文章信息:" + getArticle(article));        System.out.println("投票信息:" + getVotesUser(voted));    }    String user = "公布人1";    for (int i = 1; i < 3; i++) {        String article = "article:" + i;        String voted = "voted:" + i;        // 获取公布工夫        Double zscore = JedisUtils.zscore("time:", article);        long now = System.currentTimeMillis() / 1000;        // 生效了,不能投票        if (zscore < (now - ONE_WEEK_IN_SECONDS)) {            continue;        }        // 返回0阐明曾经存在没有插入        if (JedisUtils.sadd(voted, user) == 0) {            continue;        }        // 没有返回0怎插入胜利,顺便更新分数        JedisUtils.zincrby("score:", VOTE_SCORE, article);        // 更新文章投票数        JedisUtils.hincrBy(article, "votes", 1);    }    for (int i = 1; i < 3; i++) {        String article = "article:" + i;        String voted = "voted:" + i;        System.out.println("投票后,第一篇文章和第二篇文章的投票数:");        System.out.println("文章信息:" + getArticle(article));        System.out.println("投票信息:" + getVotesUser(voted));    }}private Map<String, String> getArticle(String article) {    Map<String, String> articleMap = JedisUtils.hgetAll(article);    return articleMap;}private Set<String> getVotesUser(String key) {    return JedisUtils.smembers(key);}

运行后果如下,能够看到,文章1被投了一票,文章2因为是作者,曾经投过票了,所以不能投票

排序

@Testpublic void sortArticle() {    // 依据工夫排序    System.out.println(JedisUtils.zrevrange("score:", 0, -1));    // 依据分值排序    System.out.println(JedisUtils.zrevrange("time:", 0, -1));}

运行后果如下,第一行后果,因为文章1被投了一票,尽管公布工夫比文章5早,然而拍在文章5后面。第二行后果就是按工夫排序的。