public class LeaderboardService {
private final RedisTemplate<String, String> redisTemplate;
public LeaderboardService(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
}
// 添加玩家到排行榜
public void addPlayerToLeaderboard(String player, double score) {
redisTemplate.opsForZSet().add("leaderboard", player, score);
}
// 获取排行榜中前 N 名玩家 /rɪˈvɜːs/
public Set<ZSetOperations.TypedTuple<String>> getLeaderboard(int topN) {
return redisTemplate.opsForZSet().reverseRangeWithScores("leaderboard", 0, topN - 1);
}
// 更新玩家在排行榜中的分数
public void updatePlayerScore(String player, double score) {
redisTemplate.opsForZSet().incrementScore("leaderboard", player, score);
}
// 从排行榜中移除玩家
public void removePlayerFromLeaderboard(String player) {
redisTemplate.opsForZSet().remove("leaderboard", player);
}
}
/**
* 一等奖1个,二等奖2个,三等奖3个,参与奖100个
*/
public class LotteryService {
private final RedisTemplate<String, String> redisTemplate;
private final JdbcTemplate jdbcTemplate;
private static final String SPOP_USER_SETS = "pop:user:set";
public LotteryService(JdbcTemplate jdbcTemplate, RedisTemplate<String, String> redisTemplate) {
this.jdbcTemplate = jdbcTemplate;
this.redisTemplate = redisTemplate;
}
public void initUserSet(String prize) {
String sql = "select id from user";
List<Map<String, Object>> userIds = jdbcTemplate.queryForList(sql);
SetOperations<String, String> ops = redisTemplate.opsForSet();
String[] ids = userIds.stream().map(item -> String.valueOf(item.get("id").toString())).toArray(String[]::new);
ops.add(SPOP_USER_SETS, ids);
}
public void drawAllPrize() {
List<String> firstPrize = drawPrize(1);
System.out.println("一等奖:" + firstPrize.get(0));
List<String> secondPrize = drawPrize(2);
System.out.println("二等奖:" + String.join(",", secondPrize));
List<String> thirdPrize = drawPrize(3);
System.out.println("三等奖:" + String.join(",", thirdPrize));
List<String> participationPrize = drawPrize(100);
System.out.println("参与奖:" + String.join(",", participationPrize));
}
/**
* 一个人最多获取一次奖品
* @param count
* @return
*/
public List<String> drawPrize(int count) {
SetOperations<String, String> ops = redisTemplate.opsForSet();
// Remove and return count random members from set at key.
return ops.pop("prize_pool", count);
}
/**
* draw 抽取
* 允许一个人多次抽取奖品
* @param count
* @return
*/
public List<String> drawPrize4duplicate(int count) {
SetOperations<String, String> ops = redisTemplate.opsForSet();
// Get count random elements from set at key.
return ops.randomMembers("prize_pool", count);
}
}
无法去重,准确
public class Stats4String {
private RedisTemplate<String, String> redisTemplate;
public Stats4String(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
}
// 比如点赞/收藏
public void incrementCount(String key) {
ValueOperations<String, String> ops = redisTemplate.opsForValue();
ops.increment(key);
}
// 比如取消点赞/取消收藏
public void decrementCount(String key) {
ValueOperations<String, String> ops = redisTemplate.opsForValue();
ops.decrement(key);
}
// 获取统计数量
public Long getCount(String key) {
ValueOperations<String, String> ops = redisTemplate.opsForValue();
String countStr = ops.get(key);
if (countStr != null) {
return Long.parseLong(countStr);
} else {
return 0L;
}
}
// 清空统计数据
public void clearCount(String key) {
redisTemplate.delete(key);
}
}
去重,不可减,不准确,节省内存
public class Stats4HyperLogLog {
private RedisTemplate<String, String> redisTemplate;
public Stats4HyperLogLog(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
}
// 添加元素到 HyperLogLog
public void addElement(String key, String... elements) {
HyperLogLogOperations<String, String> ops = redisTemplate.opsForHyperLogLog();
ops.add(key, elements);
}
// 获取 HyperLogLog 的基数估计值
public long getApproximateCount(String key) {
HyperLogLogOperations<String, String> ops = redisTemplate.opsForHyperLogLog();
return ops.size(key);
}
// 合并多个 HyperLogLog
public void mergeHyperLogLogs(String destinationKey, String... sourceKeys) {
HyperLogLogOperations<String, String> ops = redisTemplate.opsForHyperLogLog();
ops.union(destinationKey, sourceKeys);
}
// 清空 HyperLogLog
public void clearHyperLogLog(String key) {
redisTemplate.delete(key);
}
}
public class SetStats4Set {
private final RedisTemplate<String, String> redisTemplate;
public SetStats4Set(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
}
// 例如点赞
public void add(String key, String... elements) {
SetOperations<String, String> ops = redisTemplate.opsForSet();
ops.add(key, elements);
}
// 例如取消点赞
public void remove(String key, Object... elements) {
SetOperations<String, String> ops = redisTemplate.opsForSet();
ops.remove(key, elements);
}
// 例如点赞数
public long getDistinctCount(String key) {
SetOperations<String, String> ops = redisTemplate.opsForSet();
Long size = ops.size(key);
return size != null ? size : 0L;
}
// 例如点赞的人
public Set<String> members(String key) {
SetOperations<String, String> ops = redisTemplate.opsForSet();
return ops.members(key);
}
// 清空集合
public void clearSet(String key) {
redisTemplate.delete(key);
}
}
点赞数,第一个点赞的人,所有点赞的人
@Component
public class BitmapStatsService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
// 例如点赞
public void add(String key, int userId) {
setBit(key, userId, true);
}
// 例如取消点赞
public void remove(String key, int userId) {
setBit(key, userId, false);
}
// 例如点赞数
public long getDistinctCount(String key) {
return bitCount(key);
}
// 例如点赞的人
public List<Integer> members(String key) {
String value = redisTemplate.opsForValue().get(key);
List<Integer> list = new ArrayList<>();
for (byte b : value.getBytes()) {
for (int i = 7; i >= 0; i--) {
list.add((b >> i) & 1);
}
}
List<Integer> result = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == 1) {
result.add(i);
}
}
return result;
}
// 设置指定位置的位值
public void setBit(String key, long offset, boolean value) {
redisTemplate.opsForValue().setBit(key, offset, value);
}
// 获取指定位置的位值
public Boolean getBit(String key, long offset) {
return redisTemplate.opsForValue().getBit(key, offset);
}
// 统计指定范围内的位值为 true 的个数
public Long bitCount(String key) {
return redisTemplate.execute((RedisCallback<Long>) connection -> connection.bitCount(key.getBytes()));
}
public Long bitCount(String key, long start, long end) {
return redisTemplate.execute((RedisCallback<Long>) connection -> connection.bitCount(key.getBytes(), start, end));
}
// 首签时间
public Long bitPos(String key, boolean bit) {
return redisTemplate.execute((RedisCallback<Long>) connection -> connection.bitPos(key.getBytes(), bit));
}
public Long bitPos(String key, boolean bit, Long start, Long end) {
Range<Long> range = Range.closed(start, end);
return redisTemplate.execute((RedisCallback<Long>) connection -> connection.bitPos(key.getBytes(), bit, range));
}
// 连续签到/累计签到
public Long bitOp(RedisStringCommands.BitOperation op, String destination, String... keys) {
byte[][] keyBytes = new byte[keys.length][];
for (int i = 0; i < keys.length; i++) {
keyBytes[i] = keys[i].getBytes();
}
return redisTemplate.execute((RedisCallback<Long>) connection -> connection.bitOp(op, destination.getBytes(), keyBytes));
}
}