需求
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
投票
@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
執行結果如下,可以看到,文章1被投了一票,文章2由於是作者,已經投過票了,所以不能投票
排序
@Testpublic void sortArticle() { // 根據時間排序 System。out。println(JedisUtils。zrevrange(“score:”, 0, -1)); // 根據分值排序 System。out。println(JedisUtils。zrevrange(“time:”, 0, -1));}
執行結果如下,第一行結果,由於文章1被投了一票,雖然釋出時間比文章5早,但是拍在文章5前面。第二行結果就是按時間排序的。