IT俱乐部 Redis 如何使用 redis 消息队列完成秒杀过期订单处理操作(二)

如何使用 redis 消息队列完成秒杀过期订单处理操作(二)

redis 高级应用–使用 redis 消息队列完成秒杀过期订单处理

一、springDataRedis 中定义消息的监听器

1、在 JAVA 程序中监听 redis 消息:配置监听 redis 的消息。

如果要在 java 代码中监听 redis 的主题消息,需要自定义处理消息的监听器类。

2、在工程 spring-data-redis-test (模块)中,创建消息的监听器 类 RedisMessageListener.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
 *  spring-data-redis-testsrcmainjavadjhitlistenerRedisMessageListener.java
 *
 *  2024-7-24 创建消息的监听器 类 RedisMessageListener.java
 *
 *  配置 redis 消息的监听器:获取 redis 中的消息并进行处理。
 */
package djh.it.listener;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
public class RedisMessageListener implements MessageListener {
    /**
     * onMessage : 处理消息。
     *      @param message :完整的消息(频道的信息,以及消息的具体内容)
     *      @param bytes:获取的频道信息
     */
    @Override
    public void onMessage( Message message, byte[] bytes ) {
        System.out.println("从channel为:" + new String(message.getChannel())
            +"获取了一条新的消息,消息内容为:" + new String(message.getBody()));
    }
}

二、springDataRedis 中配置消息的监听器

1、配置消息的监听器:

1)监听器的适配器:(配置自定义的监听器)
2)配置监听器容器:(对监听器进行统一管理)

2、在工程 spring-data-redis-test (模块)中,修改 配置文件 applicationContext-redis.xml 添加消息监听。

1
<map></map>

三、springDataRedis 中测试消息通知

1、在工程 spring-data-redis-test (模块)中,创建 测试类 RedisTest02.java

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 *  spring-data-redis-testsrctestjavadjhitredistestRedisTest02.java
 *
 *  2024-7-24 测试类 RedisTest02.java
 */
package djh.it.redis.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class RedisTest02 {
    public static void main( String[] args ) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext-redis.xml");
    }
}

2、运行测试类 RedisTest02.java 进行消息监听,同时启动一客户端,连接 redis 服务端,

进行消息发送,观察测试类控制台输出结果:

“ 从channel为:dzs168获取了一条新的消息,消息内容为:very good ”

3、测试消息说明

1)配置好消息监听,已经订阅的主题之后就可以启动程序进行测试了。由于有监听程序在,只需要已 java 代码的形式启动,创建 spring 容器(当 spring 容器加载之后,会创建监听器一直监听对应的消息)。

2)当程序启动之后,会一直保持运行状态。即订阅了 dzs168 频道的消息,这个时候通过 redis 的客户端程序(redis-cli)发布一条消息。

3)publish topic名称 消息内容 : 向指定频道发送一条消息。

发送消息之后,我们在来看 java 控制台输出验证是否获取到了此消息。

4)至此已经完成了在 java 代码中获取 redis 的消息通知。

四、失效问题处理:业务分析以及资料介绍

1、结合 redis 的 key 失效机制和消息完成过期优惠券处理,解决过期优惠券的问题:

1)在 redis 的内部当一个 key 失效时,也会向固定的频道中发送一条消息,只需要监听到此消息获取数据库中的 id,修改对应的优惠券状态就可以了。

2)这也带来了一些繁琐的操作:用户获取到优惠券之后需要将优惠券存入 redis 服务器并设置超时时间。

3)由于要借助redis的key失效通知,有两个注意事项各位需要注意:

  • 事件通过 Redis 的订阅与发布功能(pub/sub)来进行分发,故需要订阅(__keyevent@0__:expired)频道 0表示db0 根据自己的dbindex选择合适的数字。

  • 修改 redis.conf 文件

1
2
# 添加
notify-keyspace-events Ex

2、模拟过期代金卷案例介绍:

1)使用 redis 的消息通知结合 springDataRedis 完成一个过期优惠券的处理。

2)需要两套程序,一个模拟 用户获取优惠券(coupon-achieve),一个模拟 过期优惠券的处理(coupon-expired )。

3)第一套程序:coupon-achieve

用户获取优惠券

  • 手动创建一个优惠券保存到数据库中。
  • 同时保存到 redis 服务器中,同时设置失效时间。
  • 由于 redis 中 key 的失效机制(只会发送key的失效消息)
    key(coupon:优惠券ID)-value(优惠券ID)。

4)第二套程序:coupon-expired

过期优惠券的处理

  • 订阅的主题: keyevent@0:expired配置消息监听器
  • 获取到失效消息(coupon:优惠券id),从失效消息中分离出优惠券id

查询数据库,修改优惠券状态。

3、mysql 数据库表创建。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 创建数据库
CREATE DATABASE `coupon` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
# 使用数据库
use coupon;
# 创建数据表
DROP TABLE IF EXISTS `t_coupon`;
CREATE TABLE `t_coupon` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `name` varchar(60) DEFAULT NULL COMMENT '优惠券名称',
  `money` decimal(10,0) DEFAULT NULL COMMENT '金额',
  `coupon_desc` varchar(128) DEFAULT NULL COMMENT '优惠券说明',
  `create_time` datetime DEFAULT NULL COMMENT '获取时间',
  `expire_time` datetime DEFAULT NULL COMMENT '失效时间',
  `state` int(1) DEFAULT NULL COMMENT '状态,0-有效,1-已失效,2-已使用',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

五、失效问题处理:模拟获取优惠券

1、在工程 spring-data-redis-test (模块)中,创建 测试类 RedisTest02.java

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 *  spring-data-redis-testsrctestjavadjhitredistestRedisTest02.java
 *
 *  2024-7-24 测试类 RedisTest02.java
 */
package djh.it.redis.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class RedisTest02 {
    public static void main( String[] args ) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext-redis.xml");
    }
}

2、运行测试类 RedisTest02.java 进行消息监听,同时启动一客户端,连接 redis 服务端,

进行消息发送,观察测试类控制台输出结果:

从channel为:dzs168获取了一条新的消息,消息内容为:very good

6-springDataRedis中测试消息通知.png

3、测试消息说明

1)配置好消息监听,已经订阅的主题之后就可以启动程序进行测试了。由于有监听程序在,只需要已 java 代码的形式启动,创建 spring 容器(当 spring 容器加载之后,会创建监听器一直监听对应的消息)。

2)当程序启动之后,会一直保持运行状态。即订阅了 dzs168 频道的消息,这个时候通过 redis 的客户端程序(redis-cli)发布一条消息。

3)publish topic名称 消息内容 : 向指定频道发送一条消息。

发送消息之后,我们在来看 java 控制台输出验证是否获取到了此消息。

4)至此已经完成了在 java 代码中获取 redis 的消息通知。

12-失效问题处理:业务分析以及资料介绍

redis 高级应用–使用 redis 消息队列完成秒杀过期订单处理(2)

四、失效问题处理:业务分析以及资料介绍

1、结合 redis 的 key 失效机制和消息完成过期优惠券处理,解决过期优惠券的问题:

1)在 redis 的内部当一个 key 失效时,也会向固定的频道中发送一条消息,只需要监听到此消息获取数据库中的 id,修改对应的优惠券状态就可以了。

2)这也带来了一些繁琐的操作:用户获取到优惠券之后需要将优惠券存入 redis 服务器并设置超时时间。

3)由于要借助redis的key失效通知,有两个注意事项各位需要注意:

  • 事件通过 Redis 的订阅与发布功能(pub/sub)来进行分发,故需要订阅(__keyevent@0__:expired)频道 0表示db0 根据自己的dbindex选择合适的数字。

  • 修改 redis.conf 文件

1
2
# 添加
notify-keyspace-events Ex

2、模拟过期代金卷案例介绍:

1)使用 redis 的消息通知结合 springDataRedis 完成一个过期优惠券的处理。

2)需要两套程序,一个模拟 用户获取优惠券,一个模拟 过期优惠券的处理。

3)第一套程序:coupon-achieve

用户获取优惠券

  • 手动创建一个优惠券保存到数据库中。
  • 同时保存到 redis 服务器中,同时设置失效时间。
  • 由于 redis 中 key 的失效机制(只会发送key的失效消息)
    key(coupon:优惠券ID)-value(优惠券ID)。

4)第二套程序:coupon-expired

过期优惠券的处理

  • 订阅的主题: keyevent@0:expired配置消息监听器
  • 获取到失效消息(coupon:优惠券id),从失效消息中分离出优惠券id

查询数据库,修改优惠券状态。

3、mysql 数据库表创建。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 创建数据库
CREATE DATABASE `coupon` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
# 使用数据库
use coupon;
# 创建数据表
DROP TABLE IF EXISTS `t_coupon`;
CREATE TABLE `t_coupon` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `name` varchar(60) DEFAULT NULL COMMENT '优惠券名称',
  `money` decimal(10,0) DEFAULT NULL COMMENT '金额',
  `coupon_desc` varchar(128) DEFAULT NULL COMMENT '优惠券说明',
  `create_time` datetime DEFAULT NULL COMMENT '获取时间',
  `expire_time` datetime DEFAULT NULL COMMENT '失效时间',
  `state` int(1) DEFAULT NULL COMMENT '状态,0-有效,1-已失效,2-已使用',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

13-失效问题处理:模拟获取优惠券

redis 高级应用–使用 redis 消息队列完成秒杀过期订单处理(2)

五、失效问题处理:模拟获取优惠券

1、打开 idea,创建 coupon-achieve 的 maven 工程。

1
2
3
4
5
6
7
8
9
10
11
--> idea --> File
    --> New --> Project
    --> Maven
        Project SDK: ( 1.8(java version "1.8.0_131" )
    --> Next
    --> Groupld : ( djh.it )
        Artifactld : ( coupon-achieve )
        Version : 1.0-SNAPSHOT
    --> Name: ( coupon-achieve )
        Location: ( ...coupon-achieve )
    --> Finish

2、在工程 coupon-achieve (模块)中的 pom.xml 中导入依赖

1
4.0.0cn.itcastcoupon-achieve0.0.1-SNAPSHOTwar4.2.4.RELEASE1.6.61.2.121.7.4.RELEASE8.0.23redis.clientsjedis2.6.2org.apache.commonscommons-pool22.4.2org.springframework.dataspring-data-redis${springdataredis.version}org.aspectjaspectjweaver1.6.8org.springframeworkspring-aop${spring.version}org.springframeworkspring-context${spring.version}org.springframeworkspring-orm${spring.version}org.springframeworkspring-beans${spring.version}org.springframeworkspring-core${spring.version}log4jlog4j${log4j.version}org.slf4jslf4j-api${slf4j.version}org.slf4jslf4j-log4j12${slf4j.version}org.springframeworkspring-test4.2.4.RELEASEjunitjunit4.10com.alibabadruid1.1.9mysqlmysql-connector-java${mysql.version}org.mybatismybatis3.4.5org.mybatismybatis-spring1.3.1coupon-achieveorg.apache.maven.pluginsmaven-compiler-plugin3.21.81.8UTF-8true

3、在工程 coupon-achieve (模块)中,创建实体类 Coupon.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/**
 *  redis-couponcoupon-achieve2srcmainjavacnitcastentityCoupon.java
 *
 *  2024-7-24 创建实体类 Coupon.java
 */
package cn.itcast.entity;
import java.math.BigDecimal;
import java.util.Date;
/**
 * 优惠券实体类
 */
public class Coupon {
    private Long id;//主键id
    private String name;//优惠券名称
    private BigDecimal money;//优惠券金额
    private String couponDesc;//说明
    private Date createTime;//获取时间
    private Date expireTime;//失效时间
    private Integer state;//状态 0:可用 1:已失效 2:已使用
    public Coupon() {}
    public Coupon(String name, BigDecimal money, String couponDesc, Date createTime, Date expireTime,Integer state) {
        this.name = name;
        this.money = money;
        this.couponDesc = couponDesc;
        this.createTime = createTime;
        this.expireTime = expireTime;
        this.state = state;
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public BigDecimal getMoney() {
        return money;
    }
    public void setMoney(BigDecimal money) {
        this.money = money;
    }
    public String getCouponDesc() {
        return couponDesc;
    }
    public void setCouponDesc(String couponDesc) {
        this.couponDesc = couponDesc;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Date getExpireTime() {
        return expireTime;
    }
    public void setExpireTime(Date expireTime) {
        this.expireTime = expireTime;
    }
    public Integer getState() {
        return state;
    }
    public void setState(Integer state) {
        this.state = state;
    }
    @Override
    public String toString() {
        return "Coupon [id=" + id + ", name=" + name + ", money=" + money + ", couponDesc=" + couponDesc
                + ", createTime=" + createTime + ", expireTime=" + expireTime + ", state=" + state + "]";
    }
}

4、在工程 coupon-achieve (模块)中,创建映射类 CouponMapper.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
 *  redis-couponcoupon-achieve2srcmainjavacnitcastmapperCouponMapper.java
 *
 *  2024-7-24 创建映射类 CouponMapper.java
 */
package cn.itcast.mapper;
import cn.itcast.entity.Coupon;
public interface CouponMapper {
    //保存优惠券信息
    public void saveCoupon(Coupon coupon);
    //根据id更新优惠券信息
    public void updateCoupon(Coupon coupon);
    //根据id查询优惠券信息
    public Coupon selectCouponById(long id);
}

5、在工程 coupon-achieve (模块)中,创建工具类 CouponMapper.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
 *  redis-coupon.coupon-achieve2.src.main.java.cn.itcast.utils.DataUtils.java
 *
 *  2024-7-24 创建工具类 CouponMapper.java
 */
package cn.itcast.utils;
import java.util.Calendar;
import java.util.Date;
public class DataUtils {
    public static Date addTime(Date date,int minute) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, minute);
        return calendar.getTime();
    }
}

6、在工程 coupon-achieve (模块)中,创建 配置文件 CouponMapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
id,name,money,coupon_desc,create_time,expire_time,state
 
t_coupon
 
select  from  where id =#{id,jdbcType=BIGINT}
 
insert into  (name,money,coupon_desc,create_time,expire_time,state)
values (#{name}, #{money},#{couponDesc},#{createTime}, #{expireTime}, #{state})
 
update
set name = #{name},
money = #{money},
coupon_desc = #{couponDesc},
create_time = #{createTime},
expire_time = #{expireTime},
state = #{state,jdbcType=INTEGER}
where  id = #{id,jdbcType=BIGINT}

7、在工程 coupon-achieve (模块)中,创建 applicationContext.xml 配置文件。

1
 

8、在工程 coupon-achieve (模块)中,创建 applicationContext-data-redis.xml 配置文件。

1
spring-data整合jedis

9、在工程 coupon-achieve (模块)中,创建 jdbc.properties 配置文件。

1
2
3
4
5
# redis-couponcoupon-achieve2srcmainresourcesjdbc.properties
jdbc.url=jdbc:mysql://localhost:3306/coupon
jdbc.driver=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=12311

10、在工程 coupon-achieve (模块)中,创建 sqlMapConfig.xml 配置文件。

1
 

11、在工程 coupon-achieve (模块)中,创建 log4j.properties 日志文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
# redis-couponcoupon-achieve2srcmainresourceslog4j.properties
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=debug, stdout

12、在工程 coupon-achieve (模块)中,创建测试类 CouponTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
 *  D:java-testidea2019redis-couponcoupon-achieve2srctestjavacnitcastcoupontestCouponTest.java
 *
 *  2024-7-24 创建测试类 CouponTest.java
 */
package cn.itcast.coupon.test;
import java.math.BigDecimal;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.itcast.entity.Coupon;
import cn.itcast.mapper.CouponMapper;
import cn.itcast.utils.DataUtils;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class CouponTest {
    @Autowired
    private CouponMapper couponMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * 1.创建一个优惠券
     * 2.保存到数据库中
     * 3.保存到redis服务器中,设置超时时间
     */
    @Test
    public void testGetCoupon() {
        Date now = new Date();
        int timeOut = 1;// 优惠券的超时时间:1分钟
        //自定义一个优惠券
        Coupon coupon = new Coupon();
        coupon.setName("段子手168优惠券");
        coupon.setMoney(BigDecimal.ONE);//设置金额
        coupon.setCouponDesc("全品类优惠券50元");
        coupon.setCreateTime(now);
        coupon.setExpireTime(DataUtils.addTime(now, timeOut));//设置优惠券的失效时间,一份后失效
        coupon.setState(0);
        //将优惠券保存到数据库中
        couponMapper.saveCoupon(coupon);
        //将优惠券设置到redis缓存中,并且设置超时件
        redisTemplate.opsForValue().set("coupon:"+coupon.getId(), coupon.getId()+"", timeOut, TimeUnit.MINUTES);
    }
}

13、启动 redis 服务端和客户端,运行测试类 CouponTest.java 进行测试,如下图,

在数据库中查询到插入的记录,redis 客户端也查询到数据,但 1 分钟后失效。

六、失效问题处理:配置消息监听,借助 redis 的 key 失效通知设置优惠券状态

1、打开 idea,创建 coupon-expired 的 maven 工程。

1
2
3
4
5
6
7
8
9
10
11
--> idea --> File
    --> New --> Project
    --> Maven
        Project SDK: ( 1.8(java version "1.8.0_131" )
    --> Next
    --> Groupld : ( djh.it )
        Artifactld : ( coupon-expired )
        Version : 1.0-SNAPSHOT
    --> Name: ( coupon-expired )
        Location: ( ...coupon-expired )
    --> Finish

2、 在工程 coupon-expired (模块)中的 pom.xml 中导入依赖

1
4.0.0cn.itcastcoupon-expired0.0.1-SNAPSHOTwar4.2.4.RELEASE1.6.61.2.121.7.4.RELEASE8.0.23redis.clientsjedis2.6.2org.apache.commonscommons-pool22.4.2org.springframework.dataspring-data-redis${springdataredis.version}org.aspectjaspectjweaver1.6.8org.springframeworkspring-aop${spring.version}org.springframeworkspring-context${spring.version}org.springframeworkspring-orm${spring.version}org.springframeworkspring-beans${spring.version}org.springframeworkspring-core${spring.version}log4jlog4j${log4j.version}org.slf4jslf4j-api${slf4j.version}org.slf4jslf4j-log4j12${slf4j.version}org.springframeworkspring-test4.2.4.RELEASEjunitjunit4.10com.alibabadruid1.1.9mysqlmysql-connector-java${mysql.version}org.mybatismybatis3.4.5org.mybatismybatis-spring1.3.1coupon-expiredorg.apache.maven.pluginsmaven-compiler-plugin3.21.81.8UTF-8true

3、在工程 coupon-expired (模块)中,创建监听器类 RedisMessageListener.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
 *  redis-couponcoupon-expired2srcmainjavacnitcastredislistenerRedisMessageListener.java
 *
 *  2024-7-24 创建监听器类 RedisMessageListener.java
 */
package cn.itcast.redis.listener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import cn.itcast.entity.Coupon;
import cn.itcast.mapper.CouponMapper;
public class RedisMessageListener implements MessageListener {
    @Autowired
    private CouponMapper couponMapper;
    //处理消息
    /**
     * 获取的时失效key通知:
     *      发送的消息:key(coupon:优惠券id)
     *
     *  1.接收到消息获取消息(验证是否时优惠券失效的key)
     *  2.从消息中分离出优惠券id
     *  3.查询数据库获取优惠券对象
     *  4.设置失效状态,更新数据库
     *
     */
    public void onMessage(Message message, byte[] pattern) {
        String key = new String (message.getBody());
        if(key.startsWith("coupon")) {
            String id = key.split(":")[1];
            Coupon coupon = couponMapper.selectCouponById(Long.parseLong(id));
            coupon.setState(1);
            couponMapper.updateCoupon(coupon);
        }
    }
}

4、在工程 coupon-expired (模块)中,创建实体类 Coupon.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/**
 *  redis-couponcoupon-expired2srcmainjavacnitcastentityCoupon.java
 *
 *  2024-7-24 创建实体类 Coupon.java
 */
package cn.itcast.entity;
import java.math.BigDecimal;
import java.util.Date;
/**
 * 优惠券实体类
 */
public class Coupon {
    private Long id;//主键id
    private String name;//优惠券名称
    private BigDecimal money;//优惠券金额
    private String couponDesc;//说明
    private Date createTime;//获取时间
    private Date expireTime;//失效时间
    private Integer state;//状态 0:可用 1:已失效 2:已使用
    public Coupon() {}
    public Coupon(String name, BigDecimal money, String couponDesc, Date createTime, Date expireTime,Integer state) {
        this.name = name;
        this.money = money;
        this.couponDesc = couponDesc;
        this.createTime = createTime;
        this.expireTime = expireTime;
        this.state = state;
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public BigDecimal getMoney() {
        return money;
    }
    public void setMoney(BigDecimal money) {
        this.money = money;
    }
    public String getCouponDesc() {
        return couponDesc;
    }
    public void setCouponDesc(String couponDesc) {
        this.couponDesc = couponDesc;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Date getExpireTime() {
        return expireTime;
    }
    public void setExpireTime(Date expireTime) {
        this.expireTime = expireTime;
    }
    public Integer getState() {
        return state;
    }
    public void setState(Integer state) {
        this.state = state;
    }
    @Override
    public String toString() {
        return "Coupon [id=" + id + ", name=" + name + ", money=" + money + ", couponDesc=" + couponDesc
                + ", createTime=" + createTime + ", expireTime=" + expireTime + ", state=" + state + "]";
    }
}

5、在工程 coupon-expired (模块)中,创建映射类 CouponMapper.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
 *  redis-couponcoupon-expired2srcmainjavacnitcastmapperCouponMapper.java
 *
 *  2024-7-24 创建映射类 CouponMapper.java
 */
package cn.itcast.mapper;
import cn.itcast.entity.Coupon;
public interface CouponMapper {
    //保存优惠券信息
    public void saveCoupon(Coupon coupon);
    //根据id更新优惠券信息
    public void updateCoupon(Coupon coupon);
    //根据id查询优惠券信息
    public Coupon selectCouponById(long id);
}

6、在工程 coupon-expired (模块)中,创建工具类 DataUtils.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
 *  redis-coupon.coupon-expired2.src.main.java.cn.itcast.utils.DataUtils.java
 *
 *  2024-7-24 创建工具类 DataUtils.java
 */
package cn.itcast.utils;
import java.util.Calendar;
import java.util.Date;
public class DataUtils {
    public static Date addTime(Date date,int minute) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, 10);
        return calendar.getTime();
    }
}

7、在工程 coupon-expired (模块)中,创建配置文件 CouponMapper.xml 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
id,name,money,coupon_desc,create_time,expire_time,state
 
t_coupon
 
select  from  where id =#{id,jdbcType=BIGINT}
 
insert into  (name,money,coupon_desc,create_time,expire_time,state)
values (#{name}, #{money},#{couponDesc},#{createTime}, #{expireTime}, #{state})
 
update
set name = #{name},
money = #{money},
coupon_desc = #{couponDesc},
create_time = #{createTime},
expire_time = #{expireTime},
state = #{state,jdbcType=INTEGER}
where  id = #{id,jdbcType=BIGINT}

8、在工程 coupon-expired (模块)中,创建配置文件 applicationContext.xml 。

1
 

9、在工程 coupon-expired (模块)中,创建配置文件 applicationContext-data-redis.xml。

1
spring-data整合jedis<map></map>

10、在工程 coupon-expired (模块)中,创建配置文件 jdbc.properties。

1
2
3
4
5
# redis-couponcoupon-expired2srcmainresourcesjdbc.properties
jdbc.url=jdbc:mysql://localhost:3306/coupon
jdbc.driver=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=12311

11、在工程 coupon-expired (模块)中,创建配置文件 sqlMapConfig.xml。

1
 

12、在工程 coupon-expired (模块)中,创建日志文件 log4j.properties

1
2
3
4
5
6
7
8
9
10
11
12
13
# redis-couponcoupon-expired2srcmainresourceslog4j.properties
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=debug, stdout

13、在工程 coupon-expired (模块)中,创建测试类 CouponTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
 *  redis-couponcoupon-expired2srctestjavacnitcastcoupontestCouponTest.java
 *
 *  2024-7-24 创建测试类 CouponTest.java
 */
package cn.itcast.coupon.test;
import java.math.BigDecimal;
import java.util.Date;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.itcast.entity.Coupon;
import cn.itcast.mapper.CouponMapper;
import cn.itcast.utils.DataUtils;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class CouponTest {
    @Autowired
    private CouponMapper couponMapper;
    @Test
    public void testSaveCoupon() {
        Date now = new Date();
        Coupon coupon = new Coupon("测试优惠券", BigDecimal.ONE,
                "全品类优惠10元", now, DataUtils.addTime(now, 1),0);
        couponMapper.saveCoupon(coupon );
    }
    @Test
    public void testUpdateCoupon() {
        Coupon coupon = couponMapper.selectCouponById(1l);
        coupon.setState(1);
        couponMapper.updateCoupon(coupon);
    }
    @Test
    public void selectCouponById() {
        Coupon coupon = couponMapper.selectCouponById(1l);
        System.out.println(coupon);
    }
}

14、在工程 coupon-expired (模块)中,创建测试类 RedisTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
 *  redis-couponcoupon-expired2srctestjavacnitcastredisRedisTest.java
 *
 *  2024-7-24 创建测试类 RedisTest.java
 */
package cn.itcast.redis;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext-data-redis.xml")
public class RedisTest {
    private static Logger log = Logger.getLogger(RedisTest.class);
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    public void testSend() {
        redisTemplate.opsForValue().set("itcast","very good!");
        String value = redisTemplate.opsForValue().get("itcast");
        log.info("从redis中获取的数据:"+value);
    }
}

15、在工程 coupon-expired (模块)中,创建测试类 RedisTest2.java

*/

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 *  redis-couponcoupon-expired2srctestjavacnitcastredisRedisTest2.java
 *
 *  2024-7-24 创建测试类 RedisTest2.java
 */
package cn.itcast.redis;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class RedisTest2 {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    }
}

16、启动 redis 服务端和客户端,

1)在工程 coupon-expired (模块)中,运行 测试类 RedisTest2.java 进行监听。

2)在工程 coupon-achieve (模块)中,运行测试类 CouponTest.java 进行测试,
在数据库中查询到插入的记录,redis 客户端也查询到数据,但 1 分钟后失效。
同时,mysql 数据库中的状态,由 “0” 变为 “1”。

七、总结

1、- 对于过期代金卷,红包,订单解决方案的分析

2、- redis消息队列的介绍及入门

3、- redis整合SpringData redis开发

4、- 在Java程序中监听redis消息通知

5、- 结合redis的key失效机制和消息通知完成过期订单处理

上一节关联链接请点击
# redis 高级应用–使用 redis 消息队列完成秒杀过期订单处理(1)

到此这篇关于如何使用 redis 消息队列完成秒杀过期订单处理操作的文章就介绍到这了,更多相关redis 秒杀过期订单处理内容请搜索IT俱乐部以前的文章或继续浏览下面的相关文章希望大家以后多多支持IT俱乐部!

本文收集自网络,不代表IT俱乐部立场,转载请注明出处。https://www.2it.club/database/redis/12958.html
上一篇
下一篇
联系我们

联系我们

在线咨询: QQ交谈

邮箱: 1120393934@qq.com

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部