本文Demo地址:https://gitee.com/wslxm/spring-boot-redis
一、redis 配置文件 redis.conf 修改如下
notify-keyspace-events "" 修改为 notify-keyspace-events Ex
具体参考
二、springboot 使用redis 设置key失效监听配置
1、配置监听beng
package cn.ws.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
@Configuration
public class RedisListenerConfig {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
}
2、配置redis-key 失效监听类
package cn.ws.config;
import cn.ws.constants.OrderConstants;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
/**
* Redis-key失效监听事件,所有key 失效都会走此方法
*
* @param message
* @param pattern
*/
@Override
public void onMessage(Message message, byte[] pattern) {
// 获取失效的key
String expiredKey = message.toString();
// 指定key 的前缀=xxxxxx,处理对应业务逻辑,可看步骤三生成订单号:public static final String ORDER_OVER_TIME_KEY= "order-over-time:";
if (expiredKey.indexOf(OrderConstants.ORDER_OVER_TIME_KEY) != -1) {
String[] orderOn = expiredKey.split(":");
System.out.println("订单号: "+orderOn[1] +"超时" );
}
System.out.println(expiredKey);
}
}
如果只想配置监听, 请无视下方内容
三、Redis 订单号生成分布式唯一订单号工具类
此工具类每秒可生成999999 个订单号,订单号位数为20位
- 实现思路:使用14位时间戳 + 4位自增Id (位数不够自动填充0)
- 获得时间戳:new SimpleDateFormat(“yyyyMMddHHmmss”).format(new Date());
- 获取redis自增id:opsForValue().increment(newKey, delta)
- 补位填充0到4位数:String.format("%04d", increment);
- redis集群:使用命令设置自增歩长,如步长=2,自增值= 1,3,5,7,9
- redis宕机处理:采用14位时间戳+ 4位随机数生成订单号
1、订单相关常量类
package cn.ws.constants;
/**
* TODO 订单常量类
*
* @author ws
* @mail [email protected]
* @date 2020/2/21 0021 16:02
*/
public class OrderConstants {
/**
* 订单生成redis-key前缀
*/
public static final String ORDER_ON = "order-on";
/**
* 订单生成redis-key前缀
*/
public static final String ORDER_OVER_TIME_KEY= "order-over-time:";
/**
* 订单有效期(秒)
*/
// public static final Long ORDER_OVER_TIME = 30L * 60L;
public static final Long ORDER_OVER_TIME = 10L;
}
2、订单号生成工具 RedisOrderIDGenerate
package cn.ws.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;
/**
* TODO 分布式架构获取唯一订单号(基于redis),如果redis 集群,需设置自增歩长,使用命令设置
*
* @author ws
* @mail [email protected]
* @date 2020/2/20 0020 15:02
*/
@Configuration
public class RedisOrderIDGenerate {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* TODO 获取唯一Id(20位)
*
* @param key redis-key前缀
* @param delta 默认初始自增值
* @return java.lang.String
* @author ws
* @mail [email protected]
* @date 2020/2/20 0020 15:59
*/
public String getOrderId(String key, Long delta) {
try {
// delta为空默认值1
if (null == delta) {
delta = 1L;
}
// 生成14位的时间戳(每秒使用新的时间戳当key)
String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
// 获得redis-key
String newKey = key + ":" + timeStamp;
// 获取自增值(时间戳+自定义key)
Long increment = redisTemplate.opsForValue().increment(newKey, delta);
// 设置时间戳生成的key的有效期为2秒
redisTemplate.expire(newKey, 2, TimeUnit.SECONDS);
// 获取订单号,时间戳 + 唯一自增Id( 6位数,不过前方补0)
return timeStamp + String.format("%06d", increment);
} catch (Exception e) {
// redis 宕机时采用时间戳加随机数
String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
Random random = new Random();
//14位时间戳到秒 + 4位随机数
timeStamp += random.nextInt(10) + random.nextInt(10) + random.nextInt(10) + random.nextInt(10);
return timeStamp;
}
}
}
3、订单号生成参数controller
/**
* TODO 生成订单号并测试并添加订单过期时间
*
* @author ws
* @mail [email protected]
* @date 2020/2/21 0021 16:03
*/
@RestController
public class TestController {
@Autowired
private RedisOrderIDGenerate redisOrderIDGenerate;
// redis 工具类,本次不做说明
@Autowired
private RedisUtil redisUtil;
@GetMapping("/test")
public String test() {
// 获取订单号
String orderOn = redisOrderIDGenerate.getOrderId(OrderConstants.ORDER_ON, 1L);
// 设置订单有效期30秒
redisUtil.set(OrderConstants.ORDER_OVER_TIME_KEY + orderOn, 0, OrderConstants.ORDER_OVER_TIME);
return orderOn;
}
}