Redis实现排行榜

1,542 阅读2分钟

Redis作为最为常用的非关系型数据库,具有十分优秀的性能,Redis的多种存储数据结构可以适应各种场景。

为什么使用Redis实现排行榜?

  • Redis作为一款缓存数据库,性能优异,使用Redis可以提升服务存取数据的性能。
  • Redis的zset(有序集合)数据结构,天然具备作为排行榜的优势。

怎么使用Redis实现排行榜?

  • 使用Redis的zset数据结构,其中key为固定值,value为排行榜名称,score为排行分数。
  • 我们记录点击数,每点击一次,排行榜所在的排名越高。
  • Redis的zset数据结构,使用的是从小到大的排序方式,所以我们使用负数来作为排名分数,每点击一次,排行榜的分数-1。

具体实现

搭建开发环境

Redis实现排行榜的项目环境,与Redis实现商品秒杀完全一致,需要的可以到Redis实现商品秒杀中去查看项目环境。

Dao层

  • Dao层接口
/**
 * Redis实现排名
 * @author hrp
 * 2020/3/19 16:56
 */
public interface SortDao {
    /**
     * 点击功能,修改排名,每点击一次,排名分数+1
     * @param key
     * @param name
     * @param score
     */
    void onClick(String key,String name,Double score);

    /**
     * 获取所有排名
     * @param key
     * @param start
     * @param end
     * @return
     */
    Set<String> getSort(String key, Long start, Long end);

    /**
     * 获取单个的排名分数
     * @param key
     * @param name
     * @return
     */
    Double getScore(String key,String name);
}
  • Dao层实现
@Repository
public class SortDaoImpl implements SortDao {

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void onClick(String key, String name, Double score) {
        redisTemplate.boundZSetOps(key).incrementScore(name,score);
    }

    @Override
    public Set<String> getSort(String key, Long start, Long end) {
        return redisTemplate.boundZSetOps(key).range(start, end);
    }

    @Override
    public Double getScore(String key, String name) {
        return redisTemplate.boundZSetOps(key).score(name);
    }
}

Service层

  • Service层接口
public interface SortService {
    /**
     * 点击功能,修改排名,每点击一次,排名分数+1
     * @param name
     * @param score
     */
    void onClick(String name,Double score);

    /**
     * 获取所有排名
     * @return
     */
    Set<String> getSort();

    /**
     * 获取单个的排名分数
     * @param name
     * @return
     */
    Double getScore(String name);
}
  • Service层实现
@Service
public class SortServiceImpl implements SortService {

    @Autowired
    private SortDao sortDao;

    private final static String KEY = "sort";

    @Override
    public void onClick(String name, Double score) {
        sortDao.onClick(KEY,name,score);
    }

    @Override
    public Set<String> getSort() {
        return sortDao.getSort(KEY,0L,-1L);
    }

    @Override
    public Double getScore(String name) {
        return sortDao.getScore(KEY,name);
    }
}

测试功能

@SpringBootTest
@RunWith(SpringRunner.class)
public class SortTest {

    @Autowired
    private SortService sortService;

    private final static String[] NAME = {"张三","李四","王五","赵六","田七","孙八"};

    @Before
    public void onClick(){
        for (int i = 0; i < 1000; i++) {
            String name = NAME[new Random().nextInt(6)];
            sortService.onClick(name,-1.0);
        }
    }

    @Test
    public void test(){
        Set<String> set = sortService.getSort();
        int i = 1;
        for (String str : set) {
            Double score = sortService.getScore(str);
            System.out.println("第"+i+"名为:"+str+"排名分数为:"+score);
            i++;
        }

    }
}

测试结果

1名为:孙八排名分数为:-194.02名为:张三排名分数为:-184.03名为:赵六排名分数为:-170.04名为:田七排名分数为:-153.05名为:王五排名分数为:-151.06名为:李四排名分数为:-148.0