|
@@ -1,267 +0,0 @@
|
|
|
-package com.txz.operating.dubbo.impl;
|
|
|
-
|
|
|
-import cn.hutool.core.util.StrUtil;
|
|
|
-import com.txz.operating.dto.rank.RequestRankDto;
|
|
|
-import com.txz.operating.dto.rank.ResponseRankIntro;
|
|
|
-import com.txz.operating.dto.rank.ResponseUserRankDetailDTO;
|
|
|
-import com.txz.operating.dto.rank.ResponseUserScore;
|
|
|
-import com.txz.operating.result.Result;
|
|
|
-import com.txz.operating.constants.MyConstants;
|
|
|
-import com.txz.operating.constants.RedisConstants;
|
|
|
-import com.txz.operating.core.ResultCode;
|
|
|
-import com.txz.operating.service.IOperatingRankDubboService;
|
|
|
-import com.txz.operating.util.lock.LockNameConst;
|
|
|
-import com.txz.operating.util.lock.RedissonLockUtil;
|
|
|
-import org.apache.dubbo.config.annotation.Service;
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
-import org.springframework.data.redis.core.RedisTemplate;
|
|
|
-import org.springframework.data.redis.core.ZSetOperations;
|
|
|
-
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Set;
|
|
|
-import java.util.concurrent.TimeUnit;
|
|
|
-
|
|
|
-/**
|
|
|
- * @Author: Fcx
|
|
|
- * @Date: 2019/11/25 15:07
|
|
|
- * @Version 1.0
|
|
|
- */
|
|
|
-@Service
|
|
|
-public class RankDubboServiceImpl implements IOperatingRankDubboService {
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private RedisTemplate redisTemplate;
|
|
|
-
|
|
|
- @Override
|
|
|
- public Result<List<ResponseUserScore>> getRankList(RequestRankDto dto) {
|
|
|
- if (dto.getRankKey() == null || dto.getReverse() == null
|
|
|
- || dto.getPage() == null || dto.getSize() == null) {
|
|
|
- return Result.fail(ResultCode.REQUEST_ARGS_IS_NULL.getCode(), ResultCode.REQUEST_ARGS_IS_NULL.getMessage());
|
|
|
- }
|
|
|
- // rank列表
|
|
|
- Set<ZSetOperations.TypedTuple<String>> rankList;
|
|
|
- if (dto.getReverse()) {
|
|
|
- rankList = redisTemplate.opsForZSet().reverseRangeWithScores(RedisConstants.RANK_LIST
|
|
|
- .replaceFirst("reverse", dto.getReverse().toString())
|
|
|
- .replaceFirst("rankKey", dto.getRankKey()), dto.getIndex(), dto.getSize());
|
|
|
- } else {
|
|
|
- rankList = redisTemplate.opsForZSet().rangeWithScores(RedisConstants.RANK_LIST
|
|
|
- .replaceFirst("reverse", dto.getReverse().toString())
|
|
|
- .replaceFirst("rankKey", dto.getRankKey()), dto.getIndex(), dto.getSize());
|
|
|
- }
|
|
|
- List<ResponseUserScore> list = new ArrayList<>(rankList.size());
|
|
|
- for (ZSetOperations.TypedTuple<String> tuple : rankList) {
|
|
|
- // key 转换
|
|
|
- String userId = StrUtil.subAfter(tuple.getValue(), RedisConstants.RANK_USER.replace("userId", ""), false);
|
|
|
- int score = tuple.getScore().intValue();
|
|
|
- ResponseUserScore build = ResponseUserScore.builder()
|
|
|
- .userId(userId)
|
|
|
- .score(score)
|
|
|
- .build();
|
|
|
- list.add(build);
|
|
|
- }
|
|
|
- return Result.success(list);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Result<ResponseRankIntro> getRankSizeAndTotalScore(RequestRankDto dto) {
|
|
|
- if (dto.getRankKey() == null || dto.getReverse() == null) {
|
|
|
- return Result.fail(ResultCode.REQUEST_ARGS_IS_NULL.getCode(), ResultCode.REQUEST_ARGS_IS_NULL.getMessage());
|
|
|
- }
|
|
|
- Long rankSize = redisTemplate.opsForZSet().zCard(RedisConstants.RANK_LIST
|
|
|
- .replaceFirst("reverse", dto.getReverse().toString())
|
|
|
- .replaceFirst("rankKey", dto.getRankKey())
|
|
|
- );
|
|
|
- Object o = redisTemplate.opsForValue().get(RedisConstants.RANK_TOTAL_SCORE
|
|
|
- .replaceFirst("reverse", dto.getReverse().toString())
|
|
|
- .replaceFirst("rankKey", dto.getRankKey()));
|
|
|
- Long totalScore = 0L;
|
|
|
- if (o != null) {
|
|
|
- totalScore = (Long) o;
|
|
|
- }
|
|
|
- ResponseRankIntro rankIntro = ResponseRankIntro.builder()
|
|
|
- .rankSize(rankSize)
|
|
|
- .totalScore(totalScore)
|
|
|
- .build();
|
|
|
- return Result.success(rankIntro);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Result<ResponseUserRankDetailDTO> getRankByUserId(RequestRankDto dto) {
|
|
|
- if (dto.getRankKey() == null || dto.getUserId() == null || dto.getReverse() == null) {
|
|
|
- return Result.fail(ResultCode.REQUEST_ARGS_IS_NULL.getCode(), ResultCode.REQUEST_ARGS_IS_NULL.getMessage());
|
|
|
- }
|
|
|
- // 用户的分数
|
|
|
- Double score = redisTemplate.opsForZSet().score(
|
|
|
- RedisConstants.RANK_LIST
|
|
|
- .replaceFirst("reverse", dto.getReverse().toString())
|
|
|
- .replaceFirst("rankKey", dto.getRankKey()),
|
|
|
- RedisConstants.RANK_USER
|
|
|
- .replaceFirst("reverse", dto.getReverse().toString())
|
|
|
- .replaceFirst("userId", dto.getUserId()));
|
|
|
- // 用户的排名
|
|
|
- // 取并列map,此得分的用户
|
|
|
-
|
|
|
- String parataxisRankUserId = dto.getUserId();
|
|
|
- Long rank = null;
|
|
|
- if (null != score) {
|
|
|
- Object o = redisTemplate.opsForHash().get(
|
|
|
- RedisConstants.RANK_PARATAXIS_MAP
|
|
|
- .replaceFirst("reverse", dto.getReverse().toString())
|
|
|
- .replaceFirst("rankKey", dto.getRankKey()),
|
|
|
- // key分数
|
|
|
- RedisConstants.RANK_MAP_SCORE.replace("num", String.valueOf(score.intValue()))
|
|
|
- );
|
|
|
- if (null != o) {
|
|
|
- parataxisRankUserId = (String) o;
|
|
|
- }
|
|
|
- if (dto.getReverse()) {
|
|
|
- rank = redisTemplate.opsForZSet().reverseRank(RedisConstants.RANK_LIST
|
|
|
- .replaceFirst("reverse", dto.getReverse().toString())
|
|
|
- .replaceFirst("rankKey", dto.getRankKey()),
|
|
|
- RedisConstants.RANK_USER
|
|
|
- .replaceFirst("userId", parataxisRankUserId));
|
|
|
- } else {
|
|
|
- rank = redisTemplate.opsForZSet().rank(RedisConstants.RANK_LIST
|
|
|
- .replaceFirst("reverse", dto.getReverse().toString())
|
|
|
- .replaceFirst("rankKey", dto.getRankKey()),
|
|
|
- RedisConstants.RANK_USER
|
|
|
- .replaceFirst("userId", parataxisRankUserId));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 本排行榜的人数
|
|
|
- Long rankSize = redisTemplate.opsForZSet().zCard(RedisConstants.RANK_LIST
|
|
|
- .replaceFirst("reverse", dto.getReverse().toString())
|
|
|
- .replaceFirst("rankKey", dto.getRankKey())
|
|
|
- );
|
|
|
-
|
|
|
- if (null != rank) {
|
|
|
- rank += 1;
|
|
|
- }
|
|
|
-
|
|
|
- ResponseUserRankDetailDTO detailDTO = ResponseUserRankDetailDTO.builder()
|
|
|
- .score(score)
|
|
|
- .rank(rank)
|
|
|
- .rankSize(rankSize)
|
|
|
- .build();
|
|
|
- return Result.success(detailDTO);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Result saveRankList(RequestRankDto dto) {
|
|
|
- if (dto.getRankKey() == null || dto.getUserId() == null || dto.getReverse() == null || dto.getScore() == null) {
|
|
|
- return Result.fail(ResultCode.REQUEST_ARGS_IS_NULL.getCode(), ResultCode.REQUEST_ARGS_IS_NULL.getMessage());
|
|
|
- }
|
|
|
-
|
|
|
- /// 不收集排行榜的总分 2020年11月20日 14:48:33
|
|
|
- // updateRankTotalScore(dto, true);
|
|
|
-
|
|
|
- // 更新一个用户在某个排行榜中的分数
|
|
|
- long floatNum;
|
|
|
- if (dto.getReverse()) {
|
|
|
- floatNum = System.currentTimeMillis();
|
|
|
- } else {
|
|
|
- floatNum = MyConstants.RANK_TOTAL_SCORE - System.currentTimeMillis();
|
|
|
- }
|
|
|
- redisTemplate.opsForZSet().add(
|
|
|
- RedisConstants.RANK_LIST
|
|
|
- .replaceFirst("reverse", dto.getReverse().toString())
|
|
|
- .replaceFirst("rankKey", dto.getRankKey()),
|
|
|
- RedisConstants.RANK_USER
|
|
|
- .replaceFirst("userId", dto.getUserId()),
|
|
|
-
|
|
|
- // 小数点后加一个随时间更新的值, 后面的小于前面的, 所以同分数排名是后来居上
|
|
|
- Double.valueOf(dto.getScore() + "." + floatNum)
|
|
|
- );
|
|
|
-
|
|
|
- // 更新并列map,此得分的用户
|
|
|
- redisTemplate.opsForHash().put(
|
|
|
- RedisConstants.RANK_PARATAXIS_MAP
|
|
|
- .replaceFirst("reverse", dto.getReverse().toString())
|
|
|
- .replaceFirst("rankKey", dto.getRankKey()),
|
|
|
- // key存分数
|
|
|
- RedisConstants.RANK_MAP_SCORE.replace("num", dto.getScore().toString())
|
|
|
- ,
|
|
|
- // value存userId
|
|
|
- dto.getUserId()
|
|
|
- );
|
|
|
-
|
|
|
- return Result.success();
|
|
|
- }
|
|
|
-
|
|
|
- private void updateRankTotalScore(RequestRankDto dto, Boolean update) {
|
|
|
- // 加分布式锁
|
|
|
- String lockKey = LockNameConst.LOCK_RANK_TOTAL_SCORE
|
|
|
- .replace("reverse", dto.getReverse().toString())
|
|
|
- .replace("rankKey", dto.getRankKey());
|
|
|
- // 等待5s, 10min释放
|
|
|
- if (!RedissonLockUtil.tryLock(lockKey, TimeUnit.SECONDS, 5, 60 * 10)) {
|
|
|
- throw new RuntimeException("分布式锁冲突");
|
|
|
- }
|
|
|
-
|
|
|
- // #######维护此排行榜的总分 start ######
|
|
|
- Object o = redisTemplate.opsForValue().get(RedisConstants.RANK_TOTAL_SCORE
|
|
|
- .replaceFirst("reverse", dto.getReverse().toString())
|
|
|
- .replaceFirst("rankKey", dto.getRankKey()));
|
|
|
- Long totalScore;
|
|
|
- if (o != null) {
|
|
|
- totalScore = (Long) o;
|
|
|
- } else {
|
|
|
- totalScore = 0L;
|
|
|
- }
|
|
|
-
|
|
|
- // 查出用户在排行榜里的分数,减去再加上新值
|
|
|
- Double score = redisTemplate.opsForZSet().score(
|
|
|
- RedisConstants.RANK_LIST
|
|
|
- .replaceFirst("reverse", dto.getReverse().toString())
|
|
|
- .replaceFirst("rankKey", dto.getRankKey()),
|
|
|
- RedisConstants.RANK_USER
|
|
|
- .replaceFirst("userId", dto.getUserId()));
|
|
|
- if (score != null) {
|
|
|
- totalScore = totalScore - score.longValue();
|
|
|
- }
|
|
|
-
|
|
|
- if (update) {
|
|
|
- totalScore = totalScore + dto.getScore();
|
|
|
- }
|
|
|
-
|
|
|
- redisTemplate.opsForValue().set(
|
|
|
- RedisConstants.RANK_TOTAL_SCORE
|
|
|
- .replaceFirst("reverse", dto.getReverse().toString())
|
|
|
- .replaceFirst("rankKey", dto.getRankKey()),
|
|
|
- totalScore
|
|
|
- );
|
|
|
- // #######维护此排行榜的总分 end ######
|
|
|
- RedissonLockUtil.unlock(lockKey);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Result delUserRank(RequestRankDto dto) {
|
|
|
- // 减去用户在此排行榜的总分
|
|
|
- updateRankTotalScore(dto, false);
|
|
|
-
|
|
|
- Long remove = redisTemplate.opsForZSet().remove(
|
|
|
- RedisConstants.RANK_LIST
|
|
|
- .replaceFirst("reverse", dto.getReverse().toString())
|
|
|
- .replaceFirst("rankKey", dto.getRankKey()),
|
|
|
- RedisConstants.RANK_USER
|
|
|
- .replaceFirst("userId", dto.getUserId()));
|
|
|
-
|
|
|
- return Result.success(remove);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Result delRank(RequestRankDto dto) {
|
|
|
- // 删除此排行榜的总分
|
|
|
- Boolean deleteTotalScore = redisTemplate.delete(RedisConstants.RANK_TOTAL_SCORE
|
|
|
- .replaceFirst("reverse", dto.getReverse().toString())
|
|
|
- .replaceFirst("rankKey", dto.getRankKey()));
|
|
|
- // 删除排行榜
|
|
|
- Boolean delete = redisTemplate.delete(RedisConstants.RANK_LIST
|
|
|
- .replaceFirst("reverse", dto.getReverse().toString())
|
|
|
- .replaceFirst("rankKey", dto.getRankKey()));
|
|
|
- return Result.success(deleteTotalScore && delete);
|
|
|
- }
|
|
|
-}
|