购物网站欢迎页面怎么设计外贸进口流程
web/
2025/10/7 10:24:49/
文章来源:
购物网站欢迎页面怎么设计,外贸进口流程,wordpress主页帖子不分页,建和做网站文章目录 过期监听准备工作稍微复习下Jedis与JedisPool 模拟延时队列优缺点**优点**#xff1a;**缺点**#xff1a; ZSet 实现延时队列引入依赖模拟延时队列优缺点**优点**#xff08;跟过期监听一样#xff09;#xff1a;**缺点**#xff1a; Reference Redis实现延时… 文章目录 过期监听准备工作稍微复习下Jedis与JedisPool 模拟延时队列优缺点**优点****缺点** ZSet 实现延时队列引入依赖模拟延时队列优缺点**优点**跟过期监听一样**缺点** Reference Redis实现延时队列主要有两种方式 通过SETEX 与发布订阅机制过期监听通过 ZSET 实现
过期监听
Redis通过set key and expire RedisExpirationListener 过期监听实现延时队列主要还是基于Redis的发布/订阅模式实现。
准备工作
找到redis安装目录的redis.windows.conf与redis.windows-server.conf中的“notify-keyspace-events”取消注释
notify-keyspace-events Ex然后重启下Rediswindows中会直接使用redis-server.exe不会加载redis.windows.conf这个配置文件需要用进入安装目录命令行启动
redis-server.exe redis.windows.conf如果这时命令行报错
nvalid argument during startup: unknown conf file parameter :那么要注意了Redis配置里要顶格要顶格要顶格
稍微复习下Jedis与JedisPool
首先明确一点Jedis实例不是线程安全的,所以不可以多个线程共用一个Jedis实例
那是不是要开很多个Jedis实例呢当然也不行因为更多的Jedis实例意味着要建立更多的socket连接
所以就需要JedisPool就是一个线程安全的网络连接池类似ThreadPool可以复用Thread线程实例JedisPool可以创建一些可靠的Jedis实例并且在后续复用能够提高性能并且不需要更多的Socket连接
// 开一个连接池
JedisPool jedisPool new JedisPool(127.0.0.1, 6379); // HOST, PORT
// 获取一个Jedis连接
Jedis jedis jedisPool.getResource();模拟延时队列
这里开两个线程
一个用于订阅监听事件因为subscrib()会阻塞等待需要异步初始化Jedis.subscribe(JedisPubSub实现类, channel)订阅频道需要两个参数 channel参数keyevent0:expired是发布删除过期key信息的channelJedisPubSub实现类简单来说就是实现JedisPubSub接口的一些方法当有key过期删除前/后/时执行一些逻辑 一个用于生产数据set(key, seconds, value) key这个订单集合的名字seconds过期时间(s)value当前订单的名字编号
public class RedisKeyExpireTest {private static JedisPool jedisPool new JedisPool(127.0.0.1, 6379);public static void main(String[] args) throws InterruptedException {// subscribe方法会阻塞等待用异步去初始化订阅监听事件new Thread(() - {jedisPool.getResource().subscribe(new RedisSub(), __keyevent0__:expired);}).start();// 添加几个带过期时间的keynew Thread(() - {try {for (int i 0; i 5; i) {String time LocalDateTime.now().format(DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss));jedisPool.getResource().setex(orderNo100 i, i 1, orderNo100 i);System.out.println(time :生成订单订单号orderNo100 i ,有效期 (i 1) 秒);Thread.sleep(1000);}} catch (Exception e) {e.printStackTrace();}}).start();}
}class RedisSub extends JedisPubSub {Overridepublic void onMessage(String channel, String message) {String time LocalDateTime.now().format(DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss));System.out.println(time :订单号 message 已到期);}
}
输出
2024-03-30 22:04:21:生成订单订单号orderNo1000,有效期1秒
2024-03-30 22:04:22:生成订单订单号orderNo1001,有效期2秒
2024-03-30 22:04:22:订单号orderNo1000已到期
2024-03-30 22:04:23:生成订单订单号orderNo1002,有效期3秒
2024-03-30 22:04:24:生成订单订单号orderNo1003,有效期4秒
2024-03-30 22:04:24:订单号orderNo1001已到期
2024-03-30 22:04:25:生成订单订单号orderNo1004,有效期5秒
2024-03-30 22:04:26:订单号orderNo1002已到期
2024-03-30 22:04:28:订单号orderNo1003已到期
2024-03-30 22:04:30:订单号orderNo1004已到期优缺点
优点
实现简单redis内存操作速度快性能高集群扩展方便可以通过AOF和RDB实现消息队列的持久化适合对延迟精度要求不高的业务场景
缺点 redis的key过期有惰性清除和定时清除两种策略可能会存在延迟时间不精确的问题 惰性清除不主动删除过期键每次从数据库访问 key 时都检测 key 是否过期如果过期则删除该 key 优点对 CPU 时间最友好。因为每次访问时才会检查 key 是否过期所以此策略只会使用很少的系统资源。缺点对内存不友好。如果一个 key 已经过期而这个 key 又仍然保留在数据库中那么只要这个过期 key 一直没有被访问它所占用的内存就不会释放造成了一定的内存空间浪费。 定期删除每隔一段时间「随机」从数据库中取出一定数量的 key 进行检查并删除其中的过期key如果当前抽取的key中过期的超过25%就再抽一次循环至过期比例在25%以内。 优点可以减少内存压力缺点难以确定删除操作执行的时长和频率。太频繁对CPU不友好频率太低过期key得不到及时释放对内存不友好。 而且很明显定期查询是一个循环为了保证不会循环过度导致线程卡死存在一个定期删除循环流程的时间上限默认不超过25ms 极端情况下不可靠如果客户端故障或重启期间有key过期则过期通知事件的数据就丢失了订单无法过期 可以用定时任务去做轮询补偿
ZSet 实现延时队列
Redis 可以使用有序集合ZSet的方式来实现延迟消息队列
Set 有一个 Score 属性可以用来存储延迟执行的时间
使用zadd score1 value1 生产消息利用zrangebyscore 查询符合条件的任务通过循环执行队列任务
引入依赖
dependencygroupIdredis.clients/groupIdartifactIdjedis/artifactIdversion3.2.0/version
/dependency模拟延时队列
下面模拟一下这个过程需要开两个线程
一个生产者往redis数据库里生产数据主要方法 zadd(key, value, score) key这个订单集合的名字value当前订单的名字编号score当前订单的过期时刻 一个消费者不停轮询这个key的Sorted Set主要方法 zrangeWithScores(key, start, end) 返回key中在start和end间的value和score的Tuple集合比如 zrangeWithScores(key, 0, 0)获取score最小的一个tuplezrangeWithScores(key, 0, 1)获取score最小的两个tuple 也可以用zrangeWithScores(key, start, end)这是start和end需要是准确时间。
public class CancelOrderRedisTest {private static JedisPool jedisPool new JedisPool(127.0.0.1, 6379);public static void main(String[] args) {// 开一个线程放几个订单元素到zset中new Thread(() - {try {for (int i 0; i 5; i) {String time LocalDateTime.now().format(DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss));redisClient().zadd(cancel:order:list, System.currentTimeMillis() (i 1) * 1000, orderNo100 i);System.out.println(time :生成订单订单号orderNo100 i ,有效期 (i 1) 秒);Thread.sleep(1000);}} catch (InterruptedException e) {e.printStackTrace();}}).start();// 再开一个线程轮询这个有序集合new Thread(() - {Jedis jedis redisClient();while (true){// 取这个有序集合的第一个也就是score最小的元素SetTuple items jedis.zrangeWithScores(cancel:order:list, 0, 1);if (items null || items.isEmpty()){// 避免空指针异常因为是两个线程一个线程生产数据往redis里放订单一个现在这个线程消费数据清理过期数据// 可能目前redis里的数据都消费完了所以要sleep一会等待另一个线程生产try {Thread.sleep(100);}catch (InterruptedException e){e.printStackTrace();}} else {// 轮询成功拿到redis的数据下面就判断一下是否到期Tuple tuple (Tuple) items.toArray()[0];long score (long) tuple.getScore();// 如果现在的时间大于当前数据的score过期时间进行清理if (System.currentTimeMillis() score){Long num jedis.zrem(cancel:order:list, tuple.getElement());if (num ! null num 0){String time LocalDateTime.now().format(DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss));System.out.println(time :订单号 tuple.getElement() 已到期);}}}}}).start();}/*** 获取Redis连接* return*/private static Jedis redisClient() {return jedisPool.getResource();}
}输出
2024-03-30 20:32:58:生成订单订单号orderNo1000,有效期1秒
2024-03-30 20:32:59:订单号orderNo1000已到期
2024-03-30 20:32:59:生成订单订单号orderNo1001,有效期2秒
2024-03-30 20:33:00:生成订单订单号orderNo1002,有效期3秒
2024-03-30 20:33:01:订单号orderNo1001已到期
2024-03-30 20:33:01:生成订单订单号orderNo1003,有效期4秒
2024-03-30 20:33:02:生成订单订单号orderNo1004,有效期5秒
2024-03-30 20:33:03:订单号orderNo1002已到期
2024-03-30 20:33:05:订单号orderNo1003已到期
2024-03-30 20:33:07:订单号orderNo1004已到期优缺点
优点跟过期监听一样
实现简单redis内存操作速度快性能高集群扩展方便可以通过AOF和RDB实现消息队列的持久化适合对延迟精度要求不高的业务场景
缺点
第一个就是轮询带来的问题 轮询线程如果不休眠或休眠时间过短可能导致过多的空轮询CPU飙高如果带休眠时间过长因为现在过期的数据得等到下一轮轮询才能处理延时队列的延时也就不准确了另外【没有队列的纯粹轮询】还有个问题就是数据量太大时可能一个轮询周期检查不完这里只需要轮询队头的一个或几个数据所以不太会有这个问题 然后是大部分中间件做延时队列都会有的问题 极端条件下会丢失数据不可靠比如 Redis过期通知时应用正好重启可能丢失事件导致订单一直无法关闭。先删数据在处理订单还是先处理订单再删除数据处理异常时可能会导致数据丢失。可以用定时任务去做轮询补偿 存储维护成本高需要监听的数据较大时会占用中间件大量的存储空间增加维护成本
Reference
订单超时自动取消的技术方案解析及代码实现
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/88417.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!