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数据库查询整篇文章详情。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,340评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,762评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,329评论 0 329
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,678评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,583评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,995评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,493评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,145评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,293评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,250评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,267评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,973评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,556评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,648评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,873评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,257评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,809评论 2 339

推荐阅读更多精彩内容