• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

Redis在电影票系统的设计与实现(Redis键值对设计)

互联网 diligentman 1个月前 (10-26) 20次浏览

hello你好我是辰兮 ,很早前就要整理这篇文章了,本篇是关于Redis在电影购票方面的设计与实现,设计的业务的是如何利用Redis存储对应电影排片的座位,Redis事务,乐观锁等后期会继续补充和整理,分享获取新知,大家一起进步 !

文章目录

      • 一、电影购票系统
      • 二、影厅座位设计
      • 三、电影排片设计

一、电影购票系统

本篇来讲关于Redis在电影购票系统方面的应用,主要提供Redis在设计键值方面的简单思路!

因为购票的业务是属于一个高并发的情况,而Redis作为一个优秀的缓存数据库在很大程度上可以帮助我们缓解购票压力,包括Redis本身的一些特性可以帮助我们更好的实现我们购票业务,包括乐观锁,Redis事务等等…

场景描述:
1、首先电影院会有很多电影,比如《哪吒》,《我和我的家乡》等
2、对于同一家电影院它同一部电影可以有很多的排片,即对应的影厅不一样,如情侣厅,豪华厅,VIP厅等,自然而言对应的座位也不一样

3、每一个影厅对应座位按道理后台是可以人为设置的,即设置几行几列,哪里有间隔

如特殊情况:疫情期间可以间隔排布影厅座位,影厅座位不一样

一定要能理解电影座位就是根据电影院的实际情况后台设计的

Redis在电影票系统的设计与实现(Redis键值对设计)

如上图和下图看的的就是不同的影厅
Redis在电影票系统的设计与实现(Redis键值对设计)


二、影厅座位设计

我们需要知道的两个业务逻辑,第一个是每个电影院的每个电影厅都有自己的不同名字,第二个是每个电影院的座位排布不一样,座位数目以及座位的排布可以要根据我们的实际情况,我做的是一个满足任意电影院的购票排片系统,所以我们可以根据自己的喜欢决定

如下是一个简单的草图,我可以在如下的方格中设置电影厅名称,电影厅类型,以及座位排布情况,我这样设置的就是5*5的一个座位,后面前端显示出来就是这样一个座位表!

Redis在电影票系统的设计与实现(Redis键值对设计)
这里我们的业务逻辑是将座位的数据会以Json字符串的形式存入数据库。这样没有我们设计的座位都有一个单独对应的存储Id


三、电影排片设计

这里是整个业务的核心,我们对电影院进行合理的排片,本页面包涵两个查询功能,和一个插入功能,如查询影片,查询电影厅,点击确认排片后

我们会把座位先从数据库中取出来,然后从新以Json字符串的形式存入redis中,设置过期时间,过期时间为电影开场前的五分钟,这样我们满足了电影购票的基本逻辑(开场前的五分钟无法购票)。
Redis在电影票系统的设计与实现(Redis键值对设计)

当我们打开用户前端页面显示下图

Redis在电影票系统的设计与实现(Redis键值对设计)
技术思路:Redis电影座位的设计

我们的设计如下的存储方式保证了每一部电影排片都对应唯一的id以及他的行和列都是对应的,(scheduleId)代表电影排片的唯一id。
redis-miaoyan-”+scheduleId+"-"+sd.getRowId()+"-"+sd.getColumnId()

//电影座位存储在redis中的键值设计
//"redis-miaoyan-"是用来区分,实际情况可以再短一点
//scheduleId排片表id
//sd.getRowId()+"-"+sd.getColumnId() 对应座位的行和列 用“-”隔开
"redis-miaoyan-"+scheduleId+"-"+sd.getRowId()+"-"+sd.getColumnId()**

会有一个排片表记录排片的电影,scheduleId就是记录这个排片电影的唯一id,我们用这个id来设计键值就可以更好的区分哪一场电影对应座位


技术思路:如何利用redis设计过期时间?

用redis设置过期时间要符合业务逻辑,diff就是我们设置的过期时间,过期时间为我们目前排片时候的时间减去电影开场的时间,这样电影开场就无法购票了,一般提前五分钟,所以提前五分钟清空redis。

redisTemplate.expire(“redis-miaoyan-”+scheduleId+"-"+sd.getRowId()+"-"+sd.getColumnId(),diff, TimeUnit.MINUTES);

//用expire设置键值的过期时间,这样过期后就可以释放redis相关存储资源
redisTemplate.expire("redis-miaoyan-"+scheduleId+"-"+sd.getRowId()+"-"+sd.getColumnId(),diff, TimeUnit.MINUTES);

刚刚后台设计的是5*5的座位,如图我们可以看到就是这些座位,对应的座位选上后,右侧出现几排几列,如1排6座/1排10座/5排6座/5排10座

ps:这里可以给前端加一个业务逻辑就是只能提示买四个座位,防止恶意购票。

Redis在电影票系统的设计与实现(Redis键值对设计)


如何利用好redis设计并取座位

我们的座位是管理员从后台存入的到redis的,这里取出来座位的核心代码如下

//从redis中查询对应排片Id(场次)所对应的座位信息
public List<Map<String, Object>> seatList(Integer scheduleId){
    Set<String> keyset = redisTemplate.keys("redis-miaoyan-"+scheduleId+"-*");
    List<SeatDesc> list = new ArrayList<>();
    for(String key : keyset){
        String s = redisTemplate.boundValueOps(key).get();
        list.add(new Gson().fromJson(s, SeatDesc.class));
    }
    List<Map<String, Object>> list3 = SeatServiceImpl.seatUtil(list);
    return list3;

}

回头复盘一下,每一部电影都有对应的座位和对应的厅那我们如何设计数据呢?

Redis在电影票系统的设计与实现(Redis键值对设计)
可以简单的介绍的每一次后台设置排片这个影片就有一个对应的排片ID即(Schedule ID),我们把所有和他相关座位以如下的形式存入数据库"redis-miaoyan-"+scheduleId+"-"+sd.getRowId()+"-"+sd.getColumnId()

//具体排片对应的排片id  +对应的行+对应的列
"redis-miaoyan-"+scheduleId+"-"+sd.getRowId()+"-"+sd.getColumnId()

我再以如下方式取出来
Set keyset = redisTemplate.keys(“redis-miaoyan-”+scheduleId+"-*");
这样就可以保证我每次取的座位都是当前电影排片的设置的座位

//取出来就取出来的是所有该scheduleId排片id下的redis键值  这样对应的座位就全部取出来额放到一个集合中
 Set<String> keyset = redisTemplate.keys("redis-miaoyan-"+scheduleId+"-*");

在Redis中利用 “-*” 是可以去除所有该键值的


Redis的乐观锁设置

当我们点击购票后我们的redis的座位会被锁定,这样的好处,避免两个人购买相同的座位。每一次购票到完成就相当于一次Redis的事务,我们可以思考这次购票要么成功,要么失败,不然就会导致两个人购买同一张票的情况。具体的操作如下,即确保了不能重复购买电影票。用户在选座的时候执行multi这个方法。
Redis在电影票系统的设计与实现(Redis键值对设计)


业务逻辑补充讲解

这里是我们点击购票后所进入的页面,我们可以对比上述的购票座位,检查发现是一致的,我们购票后通过redis锁定座位,和电影院的业务逻辑一样,我们设计了十五分钟的过期时间,即如果你十五分钟内未进行支付,则会出现订单支付失败,请重新购票。

这里前端和后台都要做定时器,Redis选座超过十五分钟要把这个座位释放掉,前端要提示用户在规定时间内完成支付。

这样的好处是为了防止恶意占座的情况。

Redis在电影票系统的设计与实现(Redis键值对设计)

自己整理了很久的一篇文章,如有描述不当的地方恳请大佬们指出!


The best investment is to invest in yourself.

Redis在电影票系统的设计与实现(Redis键值对设计)

2020.10.25 愿你们奔赴在自己的热爱里!


喜欢 (0)