开发者学堂课程【使用 Redis 消息队列完成秒杀过期订单处理 :失效问题处理:业务分析以及资料介绍】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/729/detail/13020
失效问题处理:业务分析以及资料介绍
内容介绍
一、业务流程
二、Java 程序实现
完成java 代码中获取 redis 的消息通知后,就可以使用 redis 的过期消息通知以及spring data redis 中的消息监听结合起来完成本次过期优惠券的处理。
一、业务流程
为了使得案例更加简单直观,业务流程分为两个部分。
1. 用户获取优惠劵
对于用户获取优惠券而言,只能根据程序进行模拟,所以采取手动创建一个优惠券保存到数据库中。
同时优惠券涉及到过期优惠券的处理,所以还需将优惠券同时保存到 redis 服务器中,给其设置一个失效时间,当其失效后借助 redis 中的机制自动发送通知。
保存到 redis 中后,因为其是一个 key 和 value 的缓存服务器,因而保存时 key 和 value 该如何取值需要明白,同时因为redis 中 key 的失效机制只会发送 key 的失效消息,所以还需要针对 key 的命名进行规范为 key(coupon:优惠券ID),同时案例中 value 并无实际用途,简写为优惠券ID即可。
- 手动创建一个优惠券保存到数据库中
- 同时保存到 redis 服务器中,同时设置失效时间
- 由于 redis 中 key 的失效机制(只会发送 key 的失效消息):
- Key(coupon:优惠券 ID)-value(优惠券 ID)
2. 过期优惠券的处理
过期优惠券的处理是通过 spring data redis 来做的,在之前也有过讲解,在此主要需要明确订阅的主题为keyevent@dbindex 即 key 的失效通知事件,可以变为@0表示将其放入0号数据库中。
配置消息的主题后还需要配置消息的监听器,在消息的监听器中需要获取到失效消息,从失效消息中分离出优惠券 id,而失效消息只会发送 key 的失效消息,所以失效消息的主体为 key:coupon :优惠券 id,获取之后就是查询数据库,同时修改优惠券状态。
- 订阅的主题:__keyevent@0__:expired
- 配置消息监听器
获取到失效消息(coupon:优惠券 id),从失效消息中分离出优惠券。
查询数据库,修改优惠券状态。
以上就是所有的处理逻辑。
二、java 程序实现
知晓业务逻辑后,可以看到如图有两个程序,其中 coupon-achieve 对应着用户获取优惠券;coupon-expired 是用来模拟过期优惠券的处理,在其中就用于处理过期优惠券。
同时因为其涉及了一些数据库表的操作,所以需要对数据库表有一定了解。此图中数据库表是为了模拟而做的一张数据库表。
其中含有 id,优惠券名称,金额,优惠券说明,获取时间和失效时间以及状态等等。
- 建表语句如下:
Create Table
CREATE TABLE 't_coupon`(
`id` bigint(2RNOT NULL AUTO_INCREMENT COMMENT'主键',
'name ` varcha60) DEFAULT NOLL COMMENT'优惠券名称',
'money decima1 (10,0)DEEAULT NULL COMMENT '金额',
‘coupon_desc` varchar(128) DEEAULT NULL COMMENT'优惠券说明',
' create_time datetime DEFAULT NOLL COMMENT'获取时间',
'expire_time’ datetime DEFAULT NULL COMMENT'失效时间',
'state' int(1) DEEAULT NULL COM4ENT '状态。0-有效,1-己失效,2-己使用',PRIMARY KEY (id`)
)ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8
用户需要获取优惠券时就相当于向表中保存一条记录,接着再向 redis 服务器中存储一条记录,有了存储记录后,获取优惠券的操作就此结束。等待优惠券失效后,再借助 redis 的失效 key 机制,在第二个程序 coupon-expired 中获取到失效 key 再去处理优惠券。
了解完流程和数据库表后,为了演示方便,老师已经将底层代码准备好,代码主要是由 mybits 基础操作数据库的代码,其中都为简单的根据 id 查询,在此不做详细说明。
- 简单 id 查询:
<select id="selectCouponById" resultMap="BaseResultNap" parameterType="Long">
selectinclude refid="Base_Column_List"/〉 from〈include refid="table" /> where id =#{id, jdbcType=BIGINT}</select>
- 简单的保存:
〈insert id="saveCoupon”parameterType="cn.itcast.entity.Coupon"useGeneratedKeys="true" keyProperty="id">
insert into<include refid="table/> (name ,money , coupon_desc ,create_time,expire_time,state)
values ( #{name},#{ money} , #{ couponDesc} , #{createTime}, #{expireTime}, #{state})
</insert>
- 简单的更新语句:
<update id="updateCoupon" parameterType="cn.itcast.entity.Coupon">
update <include refid="table/>
set name = #{name},
money = #{money},
coupon_desc = #{couponDesc},
create_time = #{ createTime},
expire_time = #{expireTime},
state = #{state,jdbcType=INTEGER}
where id = #{id,jdbcType=BIGINT}
</update>
最后以上操作无论是使用 mybits 框架还是 hibernate 框架以及原生 jdbc 操作都可以。