04_redis之ZSet使用实例-积分榜

I. 方案设计

在进行方案设计之前,先模拟一个真实的应用场景,然后进行辅助设计与实现

1. 业务场景说明

以前一段时间特别🔥的跳一跳这个小游戏进行说明,假设我们这个游戏用户遍布全球,因此我们要设计一个全球的榜单,每个玩家都会根据自己的战绩在排行榜中获取一个排名,我们需要支持全球榜单的查询,自己排位的查询这两种最基本的查询场景;此外当我的分数比上一次的高时,我需要更新我的积分,重新获得我的排名;

此外也会有一些高级的统计,比如哪个分段的人数最多,什么分段是瓶颈点,再根据地理位置计算平均分等等

本篇博文主要内容将放在排行榜的设计与实现上;至于高级的功能实现,后续有机会再说

2. 数据结构

因为排行榜的功能比较简单了,也不需要什么复杂的结构设计,也没有什么复杂的交互,因此我们需要确认的无非就是数据结构 + 存储单元

存储单元

表示排行榜中每一位上应该持有的信息,一个最简单的如下

// 用来表明具体的用户
long userId;
// 用户在排行榜上的排名
long rank;
// 用户的历史最高积分,也就是排行榜上的积分
long score;

数据结构

排行榜,一般而言都是连续的,借此我们可以联想到一个合适的数据结构LinkedList,好处在于排名变动时,不需要数组的拷贝

请添加图片描述

上图演示,当一个用户积分改变时,需要向前遍历找到合适的位置,插入并获取新的排名, 在更新和插入时,相比较于ArrayList要好很多,但依然有以下几个缺陷

问题1:用户如何获取自己的排名?

使用LinkedList在更新插入和删除的带来优势之外,在随机获取元素的支持会差一点,最差的情况就是从头到尾进行扫描

问题2:并发支持的问题?

当有多个用户同时更新score时,并发的更新排名问题就比较突出了,当然可以使用jdk中类似写时拷贝数组的方案

上面是我们自己来实现这个数据结构时,会遇到的一些问题,当然我们的主题是借助redis来实现排行榜,下面则来看下,利用redis可以怎么简单的支持我们的需求场景

3. redis使用方案

这里主要使用的是redis的ZSET数据结构,带权重的集合,下面分析一下可能性

  • set: 集合确保里面元素的唯一性
  • 权重:这个可以看做我们的score,这样每个元素都有一个score;
  • zset:根据score进行排序的集合

从zset的特性来看,我们每个用户的积分,丢到zset中,就是一个带权重的元素,而且是已经排好序的了,只需要获取元素对应的index,就是我们预期的排名

II. 功能实现

再具体的实现之前,可以先查看一下redis中zset的相关方法和操作姿势:SpringBoot高级篇Redis之ZSet数据结构使用姿势

我们主要是借助zset提供的一些方法来实现排行榜的需求,下面的具体方法设计中,也会有相关说明

0. 前提准备

首先准备好redis环境,spring项目搭建好,然后配置好redisTemplate

/**
 * Created by @author yihui in 15:05 18/11/8.
 */
public class DefaultSerializer implements RedisSerializer<Object> {
   
    private final Charset charset;

    public DefaultSerializer() {
   
        this(Charset.forName("UTF8"));
    }

    public DefaultSerializer(Charset charset) {
   
        Assert.notNull(charset, "Charset must not be null!");
        this.charset = charset;
    }


    @Override
    public byte[] serialize(Object o) throws SerializationException {
   
        return o == null ? null : String.valueOf(o).getBytes(charset);
    }

    @Override
    public Object deserialize(byte[] bytes) throws SerializationException {
   
        return bytes == null ? null : new String(bytes, charset);
    }
}


@Configuration
public class AutoConfig {
   

    @Bean(value = "selfRedisTemplate")
    public RedisTemplate
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秀才恶霸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值