马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
Redis内存淘汰策略及分布式锁应用详解
Redis内存淘汰策略
淘汰策略类型
Redis提供了多种内存淘汰策略,用于管理当内存使用到达上限时怎样处理数据。以下是六种常见的淘汰策略:
- noeviction:当内存使用到达阈值时,全部导致内存增长的命令将返回错误。
- allkeys-lru:从全部键中优先移除最近最少使用的键。(推荐)
- volatile-lru:仅从设置了逾期时间的键中优先移除最近最少使用的键。
- allkeys-random:从全部键中随机移除键。
- volatile-random:仅从设置了逾期时间的键中随机移除键。
- volatile-ttl:仅从设置了逾期时间的键中移除具有更早逾期时间的键。
设置方法
要设置Redis的内存淘汰策略,起首必要在redis.conf文件中设置最大内存限定,例如:
然后,指定内存淘汰策略:
- 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企服之家,中国第一个企服评测及商务社交产业平台。 |