https://docs.spring.io/spring-data/redis/docs/current/api/
org.springframework.data.redis.core.SetOperations 核心方法解析
add(K key, V... values)
Add given values to set at key. 插入数据
// 不存在则添加,存在则添加失败
@Nullable
Boolean addIfAbsent(K key, V value, double score);
randomMember(K key)
Get random element from set at key. 获取set 中一个随机值
public static final String SCORE_RANK = "score_rank";
public void testTank(){
Set<ZSetOperations.TypedTuple<String>> tuples = new HashSet<>(16384);
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
DefaultTypedTuple<String> tuple = new DefaultTypedTuple<>("ZHANG SAN" + i, 1D + i);
tuples.add(tuple);
}
long loopEnd = System.currentTimeMillis();
log.info("loop time:{}", loopEnd - start);
Long num = stringRedisTemplate.opsForZSet().add(SCORE_RANK, tuples);
log.info("add time:{}", System.currentTimeMillis() - loopEnd);
log.info("default num:{}", num);
// 获取前十名:
Set<String> set = stringRedisTemplate.opsForZSet().reverseRange(SCORE_RANK, 0, 10);
log.info("top 10:{}", set);
Set<ZSetOperations.TypedTuple<String>> rangeWithScores = stringRedisTemplate.opsForZSet().reverseRangeWithScores(SCORE_RANK, 0, 6);
log.info("reverseRangeWithScores:{}", rangeWithScores);
Set<String> rangeByScores = stringRedisTemplate.opsForZSet().reverseRangeByScore(SCORE_RANK, 9990D, 10000D);
log.info("reverseRangeByScore:{}", rangeByScores);
}
import com.alibaba.fastjson.JSONObject;
import com.wm.learn.demoone.redis.RankingList;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.Set;
@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = DemoOneApplication.class)
class DemoOneApplicationTests {
@Autowired
RankingList rankingList;
@Autowired
StringRedisTemplate stringRedisTemplate;
@Test
void contextLoads() {
rankingList.testTank();
}
/**
* 如果不存在则添加,存在则添加失败
*/
@Test
void addIfAbsent() {
String zhangsanV = "ZHANG SAN-11";
Boolean zhangsan1 = stringRedisTemplate.opsForZSet()
.addIfAbsent(RankingList.SCORE_RANK, zhangsanV, 100d);
log.info("1zhangsan1:{}", zhangsan1);
zhangsan1 = stringRedisTemplate.opsForZSet()
.addIfAbsent(RankingList.SCORE_RANK, zhangsanV, 100d);
log.info("2zhangsan1:{}", zhangsan1);
// 1zhang_san1:true
// 2zhang_san1:false
}
/**
* 1、根据value 添加值
* 2、删除值
* 3、
*/
@Test
void incrementScore() {
String zhangsanV1 = "ZHANG SAN-11";
String zhangsanV2 = "ZHANG SAN-12";
// 原来100 加上 100 = 200
Double zhangsanScore = stringRedisTemplate.opsForZSet()
.incrementScore(RankingList.SCORE_RANK, zhangsanV1, 100d);
log.info("zhangsanScore:{}", zhangsanScore);
// removeNum 删除成功结果,只有一个是存在,所以删除成功1个
Long removeNum = stringRedisTemplate.opsForZSet()
.remove(RankingList.SCORE_RANK, zhangsanV1, zhangsanV2);
log.info("zhangsan remove num:{}", removeNum);
// zhangsanScore:200.0
// zhangsan remove num:1
}
/**
* randomMember(K key)
* Get random element from set at key.
*/
@Test
public void randomMember(){
String randomMember = stringRedisTemplate.opsForZSet().randomMember(RankingList.SCORE_RANK);
log.info("randomMember:{}", randomMember);
}
/**
* 获取值
*/
@Test
public void get(){
String obj = "ZHANG SAN1";
// 个人分数
Long rankListNum = stringRedisTemplate.opsForZSet().reverseRank(RankingList.SCORE_RANK, obj);
log.info("{} reverseRank:{}", obj, rankListNum);
// 个人分数
Double score = stringRedisTemplate.opsForZSet().score(RankingList.SCORE_RANK, obj);
log.info("{} score:{}", obj, score);
// 逆序,从大到小,通过排名区间获取列表值和分数集合
Set<ZSetOperations.TypedTuple<String>> reverseTuples = stringRedisTemplate.opsForZSet().reverseRangeWithScores(RankingList.SCORE_RANK, 0, 1);
log.info("reverseRangeWithScores:{}", JSONObject.toJSONString(reverseTuples));
// 正序,从小到大,通过排名区间获取列表值和分数集合
Set<ZSetOperations.TypedTuple<String>> tuples = stringRedisTemplate.opsForZSet().rangeWithScores(RankingList.SCORE_RANK, 0, 1);
log.info("rangeWithScores:{}", JSONObject.toJSONString(tuples));
// 获取score为0-5的人,正序
Set<String> rankSet = stringRedisTemplate.opsForZSet().rangeByScore(RankingList.SCORE_RANK, 0, 5);
log.info("rangeByScore:{}", rankSet);
// 获取score为0-5的人,逆序
Set<String> reverseRankSet = stringRedisTemplate.opsForZSet().reverseRangeByScore(RankingList.SCORE_RANK, 0, 5);
log.info("reverseRangeByScore:{}", reverseRankSet);
// ZHANG SAN1 reverseRank:9998
// ZHANG SAN1 score:2.0
// reverseRangeWithScores:[{"score":99980.0,"value":"ZHANG SAN9997"},{"score":10000.0,"value":"ZHANG SAN9999"}]
// rangeWithScores:[{"score":1.0,"value":"ZHANG SAN0"},{"score":2.0,"value":"ZHANG SAN1"}]
// rangeByScore:[ZHANG SAN0, ZHANG SAN1, ZHANG SAN2, ZHANG SAN3, ZHANG SAN4]
// reverseRangeByScore:[ZHANG SAN4, ZHANG SAN3, ZHANG SAN2, ZHANG SAN1, ZHANG SAN0]
}
@Test
public void count(){
// key min最小score, max 最大score, 统计分数之间有多少人
Long count = stringRedisTemplate.opsForZSet().count(RankingList.SCORE_RANK, 10D, 20D);
log.info("count:{}", count);
// 统计集合总数
Long allNum = stringRedisTemplate.opsForZSet().zCard(RankingList.SCORE_RANK);
log.info("zCard:{}", allNum);
// count:11
// zCard:10000
}
@Test
public void remove(){
Set<ZSetOperations.TypedTuple<String>> tuples = stringRedisTemplate.opsForZSet().rangeByScoreWithScores(RankingList.SCORE_RANK, 0, 10);
log.info("rangeByScoreWithScores.before:{}", JSONObject.toJSONString(tuples));
// 删除某个值
Long removeNum = stringRedisTemplate.opsForZSet().remove(RankingList.SCORE_RANK, "ZHANG SAN1");
log.info("remove:{}", removeNum);
// 正序,删除某个排序范围数据
Long removeRangeNum = stringRedisTemplate.opsForZSet().removeRange(RankingList.SCORE_RANK, 0, 1);
log.info("removeRange:{}", removeRangeNum);
// 删除某个分数范围数据
Long removeRangeByScoreNum = stringRedisTemplate.opsForZSet().removeRangeByScore(RankingList.SCORE_RANK, 2, 3);
log.info("removeRangeByScore:{}", removeRangeByScoreNum);
Set<ZSetOperations.TypedTuple<String>> tuplesNext = stringRedisTemplate.opsForZSet().rangeByScoreWithScores(RankingList.SCORE_RANK, 0, 10);
log.info("rangeByScoreWithScores.tuplesNext:{}", JSONObject.toJSONString(tuplesNext));
// rangeByScoreWithScores.before:[{"score":1.0,"value":"ZHANG SAN0"},{"score":2.0,"value":"ZHANG SAN1"},{"score":3.0,"value":"ZHANG SAN2"},{"score":4.0,"value":"ZHANG SAN3"},{"score":5.0,"value":"ZHANG SAN4"},{"score":6.0,"value":"ZHANG SAN5"},{"score":7.0,"value":"ZHANG SAN6"},{"score":8.0,"value":"ZHANG SAN7"},{"score":9.0,"value":"ZHANG SAN8"},{"score":10.0,"value":"ZHANG SAN9"}]
// remove:1
// removeRange:2
// removeRangeByScore:0
// rangeByScoreWithScores.tuplesNext:[{"score":4.0,"value":"ZHANG SAN3"},{"score":5.0,"value":"ZHANG SAN4"},{"score":6.0,"value":"ZHANG SAN5"},{"score":7.0,"value":"ZHANG SAN6"},{"score":8.0,"value":"ZHANG SAN7"},{"score":9.0,"value":"ZHANG SAN8"},{"score":10.0,"value":"ZHANG SAN9"}]
}
}
实际使用场景中score 的生成方式需要多加考虑,如:同一个score 的排序问题
但凡所书,皆为来日留以回忆,反思