redis系列篇(二):redis实例演练一

需求如下:

1、用户可以发布文章或者帖子,每个用户发布的信息,从发布日期开始算,只能在一周内被点赞,且不能被同一个用户重复点赞。

2、文章或者帖子信息可以按照积分或者时间来进行排序,且能够分页显示。

3、每个用户发布的文章应该归属到一个组里面,例如张三发布的属于科技篇和互联网篇,李四发布的属于互联网篇和人工智能篇,王五发布的属于互联网篇

4、归组以后可以查询出任何组与组之间交集的文章或者帖子信息。

需求分析:

1、首先我们需要知道文章信息应该用redis哪种方式去存储,纵观其五种存储方式,选择了hash,为什么呢,因为hash方便扩展和维护,后期需要修改里面某个字段内容非常方便或者新增字段也非常方便。

2、控制一周内部被重复点赞,则直接设置文章的点赞过期时间即可,每次点赞前先判断文章是否有效

3、控制重复点赞用set方式存储,技能统计点赞用户集合,又能控制重复

4、既然涉及到排序,那么毫无疑问用sortSet方式存储

5、这里注意到无论是交集、并集、差集都只能用set集合去存。

代码如下:

package redis.clients.test;

import java.util.ArrayList;

import java.util.Date;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import java.util.Set;

import org.junit.Test;

import redis.clients.jedis.Jedis;

import redis.clients.util.DateTimeUtil;

public class D01_Test {

private static final int ONE_WEEK_IN_SECONDS = 7 * 86400;//每周多少秒  控制点赞过期时间

private static final int VOTE_SCORE = 10;//点赞积分

private static final int ARTICLES_PER_PAGE = 25;//每页多少篇文章

static Jedis jedis=null;

static{

jedis=new Jedis("127.0.0.1");

}

/**

* 用户发布文章信息

* @param wzzt   文章主题

* @param wznr文章内容

* @param wzzb   文章组别   多个用逗号","隔开

* @param username  用户名

* @return

*/

public String postArticle(String wzzt,String wznr,String wzzb,String username){

try {

/**

* 用hash方式存放文章信息(hash方式方便扩展子弹和修改数据)

*/

String id=DateTimeUtil.getDateSecondFormatNoSplit(new Date());

Map articleMap=new HashMap();

articleMap.put("wzzt", wzzt);

articleMap.put("wzid", id);

articleMap.put("wznr", wznr);

articleMap.put("username", username);

articleMap.put("fbsj", DateTimeUtil.getDateSecondFormat(new Date()));//文章发布时间

articleMap.put("votes", "1");//初始化文章的点赞信息

jedis.hmset("article:"+id, articleMap);

/**

* 控制文章点赞的过期时间为一周(set集合可以去重,设置过期时间)

*/

jedis.sadd("voted:"+id, username);//默认存在自己点赞信息

jedis.expire("voted:"+id, ONE_WEEK_IN_SECONDS);

/**

* 存放文章对应积分和时间 --初始化积分为100  (排序必须用sortSet集合方式)

*/

jedis.zadd("article_score:", 100, "article:"+id);

jedis.zadd("article_time:", System.currentTimeMillis() / 1000, "article:"+id);

/**

* 分组存放文章信息 (只有set集合才可以去交集、并集、差集)

*/

String[] wzzbs=wzzb.split(",");

for (int i = 0; i < wzzbs.length; i++) {

String str=wzzbs[i];//遍历出每个组别的名称

jedis.sadd("article_group:"+str, "article:"+id);//此处只能用set集合存放组别,因为需要取交集

}

System.out.println(username+"============文章发布成功===========");

return "1";

} catch (Exception e) {

System.out.println("文章发布异常!");

return "-1";

}

}

/**

* 点赞操作

* @param wzid        文章ID

* @param username    点赞用户

* @return

*/

public int votedArticle(String wzid,String username){

try {

//文章只有在一周内才可以被点赞,在发布文章的时候此处的key过期时间为1周

if(jedis.exists("voted:"+wzid)){

//判断是否用户重复点赞

long num=jedis.sadd("voted:"+wzid, username);//因为当用户点赞后,此处再次新增时结果为0

if(num==1){

System.out.println(username+"点赞成功");

jedis.zincrby("article_score:", VOTE_SCORE, "article:"+wzid);//加积分

jedis.hincrBy("article:"+wzid, "votes", 1L);//修改hash里面的点赞数量

return 1;

}else{

System.out.println(username+"不允许重复点赞");

return -1;

}

}else{

System.out.println("文章已超过点赞时间,不允许点赞");

return -1;

}

} catch (Exception e) {

System.out.println("文章点赞异常!");

return -1;

}

}

/**

* 分页倒序查询文章信息

* @param type   1-按照积分  2-按照时间

* @param pageNum 当前页数

* @return

*/

public List> getArticles(String type,int pageNum){

List> lists=new ArrayList>();

try {

int start = (pageNum - 1) * ARTICLES_PER_PAGE;//0

int end = start + ARTICLES_PER_PAGE - 1;//24

if("1".equals(type)){

Set sets= jedis.zrevrange("article_score:", start, end);

for (String id : sets) {

Map data=jedis.hgetAll(id);

lists.add(data);

}

}else{

Set sets= jedis.zrevrange("article_time:", start, end);

for (String id : sets) {

Map data=jedis.hgetAll(id);

lists.add(data);

}

}

} catch (Exception e) {

System.out.println("查询文章信息失败");

}

return lists;

}

/**

* 分组获取对应文章信息

* 此处分组交集查询是不能按照规则去排序的,

* 如果需要排序,可以在hash里面加时间和积分或者点赞数量字段后,直接将此处的List集合按照对应条件进行排序

* @param groups   组别 按照逗号分隔 ","

* @return

*/

public List> getArticlesByGroup(String groups){

List> lists=new ArrayList>();

try {

String[] strs=groups.split(",");

Set sets= jedis.sinter(strs);

for (String id : sets) {

Map data=jedis.hgetAll(id);

lists.add(data);

}

} catch (Exception e) {

System.out.println("分组查询文章信息失败");

}

return lists;

}

@Test

public void testD01_Test(){

D01_Test test=new D01_Test();

/**

* 第一步:张三 、李四 、王五各发布一篇文章,

*      其中张三发布文章为科技(technology)篇和互联网(internet)篇

*      李四发布文章互联网(internet)篇和人工智能(artificial)篇

*      王五发布的属于互联网(internet)篇

//jedis.flushDB();

test.postArticle("张三测试", "张三发布的问内容为科技篇和互联网篇", "technology,internet", "zhangsan");

// test.postArticle("李四测试", "李四发布文章互联网和人工智能", "internet,artificial", "lisi");

// test.postArticle("王五测试", "王五发布的为互联网篇", "internet", "wangwu");

*/

/**

* 第二步:

* 李四和王五都点赞张三           张三的文章ID=20170725143410

* 王五点赞李四李四的文章ID=20170725143502

* 王五再次点赞张三王五的文章ID=20170725143532

*/

// test.votedArticle("20170725143410","lisi");

//test.votedArticle("20170725143410","wangwu");

// test.votedArticle("20170725143502","wangwu");

// test.votedArticle("20170725143410","wangwu");

/**

* 第三步:此时查询出所有文章内容

List> resultLists=test.getArticles("1", 1);

System.out.println("==========按照积分倒叙排序start==========");

System.out.println(resultLists);

System.out.println("==========按照积分倒叙排序end==========");

List> resultLists2=test.getArticles("2", 1);

System.out.println("==========按照时间倒叙排序start==========");

System.out.println(resultLists2);

System.out.println("==========按照时间倒叙排序end==========");*/

/**

*第四步:

*    查询和互联网相关的文章

*    查询出互联网 、科技相关的文章

*/

/* List> resultLists3=test.getArticlesByGroup("article_group:internet");

System.out.println("==========按照组别交集查询为互联网的文章start==========");

System.out.println(resultLists3);

System.out.println("==========按照组别交集查询为互联网的文章end==========");*/

List> resultLists4=test.getArticlesByGroup("article_group:internet,article_group:technology");

System.out.println("==========按照组别交集查询为互联网且为科技的文start==========");

System.out.println(resultLists4);

System.out.println("==========按照组别交集查询为互联网且为科技的文end==========");

}

}

总结分析:实际上很多人会疑问,一篇文章或者帖子起始数据量很大,redis能否承受,当然,文章的整篇内容是不适合存放在redis中的,毕竟数据量比较大,所以这里适合去存放每篇文章或者帖子的简单主题介绍,这样无论是在PC端还是APP端都可以很快查询出对应的列表信息,当点击某一篇文章时,再去mysql或者oracle数据库查询整篇文章详情。

你可能感兴趣的:(redis系列篇(二):redis实例演练一)