IT评测·应用市场-qidao123.com技术社区
标题:
《Redis内存淘汰策略及分布式锁应用详解》
[打印本页]
作者:
张春
时间:
2024-11-14 06:25
标题:
《Redis内存淘汰策略及分布式锁应用详解》
Redis内存淘汰策略及分布式锁应用详解
Redis内存淘汰策略
淘汰策略类型
Redis提供了多种内存淘汰策略,用于管理当内存使用到达上限时怎样处理数据。以下是六种常见的淘汰策略:
noeviction
:当内存使用到达阈值时,全部导致内存增长的命令将返回错误。
allkeys-lru
:从全部键中优先移除最近最少使用的键。(推荐)
volatile-lru
:仅从设置了逾期时间的键中优先移除最近最少使用的键。
allkeys-random
:从全部键中随机移除键。
volatile-random
:仅从设置了逾期时间的键中随机移除键。
volatile-ttl
:仅从设置了逾期时间的键中移除具有更早逾期时间的键。
设置方法
要设置Redis的内存淘汰策略,起首必要在redis.conf文件中设置最大内存限定,例如:
maxmemory 300mb
复制代码
然后,指定内存淘汰策略:
maxmemory-policy allkeys-lru
复制代码
Redis中的主动逾期机制与订单逾期主动取消
主动逾期机制
Redis允许为键设置一个生存时间(TTL),一旦键逾期,它会被主动删除。这一特性可以用来实现诸如订单逾期主动取消的功能。
实现方案
使用Redis Key主动逾期触发事件通知
:设置Redis以通知逾期事件。
使用定时使命检查
:设定一个定时使命定期检查逾期订单。
按分钟轮询检查
:每隔一段时间轮询检查是否有订单逾期。
示例:Spring Boot整合Redis键逾期监听
假设有一个订单表order_number,当订单30分钟内未付出时,应主动将订单状态更改为已取消。
表结构
CREATE TABLE `order_number` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_name` varchar(255) DEFAULT NULL,
`order_status` int(11) DEFAULT NULL,
`order_token` varchar(255) DEFAULT NULL,
`order_id` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8;
复制代码
Redis设置
在redis.conf中启用键逾期通知:
notify-keyspace-events "Ex"
复制代码
Spring Boot设置
@Configuration
public class RedisListenerConfig {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
}
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
private static final Integer ORDER_STAYPAY = 0;
private static final Integer ORDER_INVALID = 2;
@Autowired
private OrderMapper orderMapper;
@Override
public void onMessage(Message message, byte[] pattern) {
String expiredKey = message.toString();
OrderEntity order = orderMapper.getOrderNumber(expiredKey);
if (order != null && order.getOrderStatus().equals(ORDER_STAYPAY)) {
orderMapper.updateOrderStatus(expiredKey, ORDER_INVALID);
}
}
}
复制代码
控制器
@RestController
public class OrderController {
@Autowired
private OrderMapper orderMapper;
@Autowired
private RedisUtils redisUtils;
@RequestMapping("/saveOrder")
public String saveOrder() {
String orderToken = UUID.randomUUID().toString();
String orderId = System.currentTimeMillis() + "";
redisUtils.setString(orderToken, orderId, 30L); // 30分钟
OrderEntity orderEntity = new OrderEntity(null, "蚂蚁课堂永久会员", orderId, orderToken);
int result = orderMapper.insertOrder(orderEntity);
return result > 0 ? "success" : "fail";
}
}
复制代码
Redis事件操作
Redis事件通过MULTI、EXEC、WATCH和DISCARD命令来实现。事件确保一系列命令要么全部执行,要么都不执行,但Redis并不支持事件回滚。
事件与回滚的区别
取消事件
:不提交事件,事件中的全部操作都不会被执行。
回滚
:事件中的全部操作被撤销,恢复到事件开始前的状态。Redis不支持此功能。
Redis实现分布式锁
分布式锁原理
分布式锁是一种在分布式体系中实现互斥访问共享资源的机制。Redis通过SETNX命令实现分布式锁,该命令只有在键不存在时才会设置键。
核心代码示例
public class RedisUtil {
private static String IP = "192.168.212.148";
private static int PORT = 6379;
private static int MAX_ACTIVE = 100;
private static int MAX_IDLE = 20;
private static int MAX_WAIT = 3000;
private static int TIMEOUT = 3000;
private static boolean TEST_ON_BORROW = true;
private static boolean TEST_ON_RETURN = true;
private static JedisPool jedisPool = null;
public final static int EXRP_HOUR = 60 * 60;
public final static int EXRP_DAY = 60 * 60 * 24;
public final static int EXRP_MONTH = 60 * 60 * 24 * 30;
private static void initialPool() {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(MAX_ACTIVE);
config.setMaxIdle(MAX_IDLE);
config.setMaxWaitMillis(MAX_WAIT);
config.setTestOnBorrow(TEST_ON_BORROW);
jedisPool = new JedisPool(config, IP, PORT, TIMEOUT, "123456");
}
private static synchronized void poolInit() {
if (jedisPool == null) {
initialPool();
}
}
public synchronized static Jedis getJedis() {
if (jedisPool == null) {
poolInit();
}
return jedisPool.getResource();
}
public static void returnResource(Jedis jedis) {
if (jedis != null && jedisPool != null) {
jedisPool.returnResource(jedis);
}
}
public static Long sadd(String key, String... members) {
Jedis jedis = null;
Long res = null;
try {
jedis = getJedis();
res = jedis.sadd(key, members);
} catch (Exception e) {
e.printStackTrace();
} finally {
returnResource(jedis);
}
return res;
}
}
复制代码
应用场景
分布式使命调度
:确保同一使命不会被重复执行。
分布式全局ID生成
:生成唯一标识符。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/)
Powered by Discuz! X3.4