如果對實時並發排序感興趣,請關注這個項目(java):https://github.com/xuerong/hqrank,歡迎參與開發,pass:支持多字段排行
最近遇到一個問題就是根據需求需要對所有的用戶根據積分,顯示他的全站排名,數據量大概200萬左右,積分是實時更改的,怎么能讓這個排名盡量的實時呢?一直很困惑,之前用過db的count查,速度很慢,並且高峰時候db也容易堵住。
這個實時性排序要求高,不建議用db做,db只是恢復數據用,排序及前端獲取排行列表,我推薦用redis,數據結構采用其內置的sorted list,性能非常好,redis只保存最簡單的id+積分這么一個數據,關閉實體化選項,全部用內存來保存數據,搭建主從防止宕機,然后自己實現一個從db到redis的數據恢復過程即可。
數據保存的話,根據你實際並發量考慮,並發不高的話可以定時寫入db,並發很高的話,中間需要再做一個緩沖隊列。
Jedis 是 Redis 官方首選的 Java 客戶端開發包。這篇文章我們將介紹如何使用 Sorted Set 排序集合(zsets)。
Sorted Set 跟一個集合一樣,它是不會存在重復的數值,最大的不同是 Sorted Set 中每個元素都是經過排序的。
我們先看一些命令:
import java.util.HashMap;
import java.util.Map; import redis.clients.jedis.Jedis; public class TestJedis { public static void main(String[] args) { String key = "mostUsedLanguages"; Jedis jedis = new Jedis("localhost"); //Adding a value with score to the set jedis.zadd(key,100,"Java");//ZADD //We could add more than one value in one calling Map<Double, String> scoreMembers = new HashMap<Double, String>(); scoreMembers.put(90d, "Python"); scoreMembers.put(80d, "Javascript"); jedis.zadd(key, scoreMembers); //We could get the score for a member System.out.println("Number of Java users:" + jedis.zscore(key, "Java")); //We could get the number of elements on the set System.out.println("Number of elements:" + jedis.zcard(key));//ZCARD } }
上述例子中我們看到了 Zset 命令,為了將元素添加到 zet 中,我們使用 zadd 方法,不同的是我們還傳遞了一個元素的評分值,我們可以使用 Map 對象來一次傳遞很多個對象,而 zadd 方法可用於增加和更新已有元素的評分值。
我們可使用 zscore 來獲取某元素的評分,通過 zcard 獲取元素個數。
下面的例子我們可看到來自 zsets 的其他命令:
import java.util.Set;
import redis.clients.jedis.Jedis; import redis.clients.jedis.Tuple; public class TestJedis { public static void main(String[] args) { String key = "mostUsedLanguages"; Jedis jedis = new Jedis("localhost"); //get all the elements sorted from bottom to top System.out.println(jedis.zrange(key, 0, -1)); //get all the elements sorted from top to bottom System.out.println(jedis.zrevrange(key, 0, -1)); //We could get the elements with the associated score Set<Tuple> elements = jedis.zrevrangeWithScores(key, 0, -1); for(Tuple tuple: elements){ System.out.println(tuple.getElement() + "-" + tuple.getScore()); } //We can increment a score for a element using ZINCRBY System.out.println("Score before zincrby:" + jedis.zscore(key, "Python")); //Incrementing the element score jedis.zincrby(key, 1, "Python"); System.out.println("Score after zincrby:" + jedis.zscore(key, "Python")); } }
通過 zrange 我們能獲取給定范圍的元素,它將返回經過排序后的元素列表(自底向上),也可以通過 zrevrrange 獲取自頂向下的元素列表。Redis 還允許我們通過關聯的評分來獲取元素,傳遞 “withscores“ 參數即可。使用 Jedis API 的 zrevrangeWithScores 方法可返回對象集合。另外一個有用的命令是 zincrby 可用於增加元素的評分值。
zsets 還有其他的命令,這里我們只是介紹跟 Jedis API 相關的一些基本用法。這里還有一些關於排序集合的介紹。