本文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;
}
}