redis实战--文章投票

一、 确定投票系统结构

  1. hash来存储文章
    key:article:110
    titile:文章标题
    link:链接
    votes:投票数
    user:文章作者

  2. zset存储文章发布时间

  3. zset存储文章得分

  4. set集合存储每一篇文章的投票的用户
    vote:110
    user:1
    user:2

二、考虑生成文章

需要将文章属性以Map集合的形式传入到hash结构中,之后在对应score与time添加当前文章

// 发布文章
	public static String postArticle(Jedis conn, String user, String link, String title) {
		String article = String.valueOf(conn.incr("article:"));
		String voted = "voted:" + article;
		conn.sadd(voted, user);
		conn.expire(voted, week_time);
		long now = System.currentTimeMillis() / 100;// 当前秒数
		String articleName = "article:" + article;
		HashMap<String, String> map = new HashMap<String, String>();
		map.put("link:", link);
		map.put("title:", title);
		map.put("user:", user);
		map.put("votes:", "1");
		conn.hmset(articleName, map);
		conn.zadd("score:", now + var_voted, articleName);
		conn.zadd("time:", now, articleName);
		return article;
	}

三、 考虑投票模型

投票的时候需要去关注两点:1、只有文章在有效期之内才能投票2、文章得票属性增加
3、文章score增加

// 投票
	public static void articleVote(Jedis conn, String user, String article) {
		long diff = System.currentTimeMillis() / 1000 - week_time;
		if (conn.zscore("time:", article) < diff) {
			return;
		}
		String articleID = article.substring(article.indexOf(":") + 1);
		if (conn.sadd("voted:" + articleID, user) == 1) {
			conn.zincrby("score:", var_voted, article);// 投票分数增加
			conn.hincrBy(article, "votes:", 1);
		}
	}

四、考虑获取文章模型

设定参数,每一次获取指定数量的文章,
由于需要满足文章点赞排名,此时就需要去根据分数从大到小排序(zrevrange实现),之后根据返回的article,在hash文章结构中找到对应文章属性。

public static List<Map<String, String>> getArticle(Jedis conn, int page) {
		return getArticle(conn, page, "score:");
	}

	// 获取文章信息
	public static List<Map<String, String>> getArticle(Jedis conn, int page, String order) {
		List<Map<String, String>> list = new ArrayList<Map<String, String>>();
		int start = (page - 1) * per_page;
		int end = start + per_page - 1;
		Set<String> idSet = conn.zrevrange(order, start, end);// 所有文章
		System.out.println(conn.type(order));
		for (String id : idSet) {
			Map<String, String> map = conn.hgetAll(id);// 文章数据
			map.put("id:", id);
			list.add(map);
		}
		return list;
	}

  • 考虑分组功能
    1、需要去新建一个set结构,用来存储每一种类型的文章
    2、分组查询:是通过两个zset结合(score集合与某一类文章集合)求交集,分组中也要按照得分从高到低来排序,找到共有的文章id,之后去hash结构中查找详细信息
// 群组删除功能
	public static void delGroup(Jedis conn, String articleID, String[] groups) {
		String article = "article:" + articleID;
		for (String group : groups) {
			if (conn.sismember("group:" + group, article)) {
				conn.srem("group:" + group, article);
			}
		}
	}

	// 得到群组文章
	public static List<Map<String, String>> getGroupArticle(Jedis conn, String group, int page) {
		return getGroupArticle(conn, group, page, "score:");
	}

	public static List<Map<String, String>> getGroupArticle(Jedis conn, String group, int page, String order) {
		String key = order + group;
		if (!conn.exists(key)) {
			// 将两个表关联求交集,找到同组中分数高的文章
			ZParams params = new ZParams().aggregate(ZParams.Aggregate.MAX);
			conn.zinterstore(key, params, "group:" + group, order);
			conn.expire(key, 60);// 60s有效期
		}
		return getArticle(conn, page, key);// 找到群组里排序后的文章
	}

五、 打印文章

// 打印文章
	public static void printArticle(List<Map<String, String>> articleList) {
		for (Map<String, String> map : articleList) {

			for (Map.Entry<String, String> entry : map.entrySet()) {
				if (entry.getKey().equals("id")) {
					System.out.println(entry.getValue());
				} else {
					System.out.print(entry.getKey() + " " + entry.getValue());
				}
			}
			System.out.println();
		}
	}

  • test
    主要包括新建文章测试、文章投票测试、文章分组测试,分组排名展示
    public static final int week_time = 7 * 86400;
	public static final int var_voted = 432;
	public static final int per_page = 25;
    public static void main(String[] args) {
		new Chapter01().run();
	}

	public static void run() {
		Jedis jedis = new Jedis("127.0.0.1", 6379);
		System.out.println("新建文章:");
		String articleID = postArticle(jedis, "robin",                                       "http://www.baidu.com", "成功学");
		System.out.println("article:" + articleID);
		Map<String, String> map = jedis.hgetAll("article:" + articleID);
		for (Map.Entry<String, String> entry : map.entrySet()) {
			System.out.println(" ");
			System.out.print(entry.getKey() + " " + entry.getValue());
		}
		System.out.println(" ");
		System.out.println("开始为当前文章投票:");
		articleVote(jedis, "other_user", "article:" + articleID);
		String votes = jedis.hget("article:" + articleID, "votes:");
		System.out.println("当前文章获取票数votes:" + votes);
		assert Integer.parseInt(votes) > 1;
		System.out.println(" ");
		System.out.println("最高分数分组展示");
		List<Map<String, String>> list = getArticle(jedis, 1);
		printArticle(list);
		assert list.size() > 1;
		System.out.println("分组展示功能");
		addGroup(jedis, articleID, new String[] { "newGroup" });
		List<Map<String, String>> list2 = getGroupArticle(jedis, "newGroup", 1);
		printArticle(list2);
		assert list2.size() > 1;

	}

  • 参考:本人正在学习redis,主要是自己动手实现一下《redis in action》chapter01demo
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值