Kaedah tinjauan berjadual pangkalan data, idea pelaksanaannya agak mudah. Mulakan tugas yang dijadualkan, imbas jadual pesanan pada masa tertentu dan batalkan pesanan tamat masa selepas menanyakannya.
Kelebihan: Mudah dilaksanakan.
Kelemahan: Selang pengundian sukar ditentukan, menduduki sumber pelayan dan menjejaskan prestasi pangkalan data.
Apabila menanyakan maklumat pesanan, mula-mula tentukan sama ada pesanan telah tamat masa, dan jika tamat masa, batalkannya dahulu.
Kelebihan: Mudah dilaksanakan.
Kelemahan: Ia mempengaruhi perniagaan selain pertanyaan (seperti statistik, inventori) dan menjejaskan kecekapan pertanyaan.
Baris Gilir Kelewatan JDK DelayQueue ialah baris gilir sekatan tanpa sempadan, yang hanya boleh mendapatkan elemen daripadanya apabila kelewatan tamat tempoh.
Demo kod pelaksanaan yang mudah adalah seperti berikut Dalam proses pengeluaran sebenar, akan ada urutan khusus yang bertanggungjawab untuk queuing dan penggunaan mesej.
import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit; /** * @author 向振华 * @date 2022/08/16 15:55 */ public class OrderDelayed implements Delayed { /** * 延迟时间 */ private final Long time; /** * 订单编号 */ public String orderNo; public OrderDelayed(String orderNo, long time, TimeUnit unit) { this.orderNo = orderNo; this.time = System.currentTimeMillis() + (time > 0 ? unit.toMillis(time) : 0); } @Override public long getDelay(TimeUnit unit) { return time - System.currentTimeMillis(); } @Override public int compareTo(Delayed o) { OrderDelayed orderDelayed = (OrderDelayed) o; long diff = this.time - orderDelayed.time; if (diff <= 0) { return -1; } else { return 1; } } }
Kelebihan: kecekapan tinggi, kelewatan masa pencetus tugas yang rendah.
Kelemahan: Kesukaran dalam pemulihan pengecualian, pengembangan kluster yang menyusahkan, penggunaan memori.
Algoritma roda masa adalah serupa dengan jam dan akan berputar ke arah tertentu pada frekuensi tetap. Anda boleh menggunakan HashedWheelTimer Netty untuk melaksanakan kaedah roda masa.
import java.util.concurrent.DelayQueue; import java.util.concurrent.TimeUnit; /** * @author 向振华 * @date 2022/08/16 16:02 */ public class Test { public static void main(String[] args) { DelayQueue<OrderDelayed> delayQueue = new DelayQueue<>(); delayQueue.put(new OrderDelayed("220101001", 8, TimeUnit.SECONDS)); delayQueue.put(new OrderDelayed("220101002", 4, TimeUnit.SECONDS)); System.out.println("订单延迟队列开始执行"); while (true) { // 取队列头部元素是否过期 OrderDelayed task = delayQueue.poll(); if (task != null) { // 取消订单业务逻辑 System.out.println("订单 ---> " + task.orderNo + " 已过期准备取消"); } } } }
Kelebihan: kecekapan tinggi, kelewatan masa pencetus tugas yang lebih rendah.
Kelemahan: Kesukaran dalam pemulihan pengecualian, pengembangan kluster yang menyusahkan, penggunaan memori.
Acara panggil balik tamat tempoh kekunci Redis juga boleh mencapai kesan melambatkan baris gilir.
Tambahkan konfigurasi dalam redis.conf:
notify-keyspace-events Ex
Konfigurasi mendengar
<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.78.Final</version> </dependency>
Panggil balik tamat tempoh Redis Kaedah pemantauan
import io.netty.util.HashedWheelTimer; import io.netty.util.Timeout; import io.netty.util.Timer; import io.netty.util.TimerTask; import java.util.concurrent.TimeUnit; /** * @author 向振华 * @date 2022/08/16 16:02 */ public class Test { public static void main(String[] args) { // 初始化时间轮 Timer timer = new HashedWheelTimer(); // 定时任务 TimerTask task1 = new TimerTask() { public void run(Timeout timeout) throws Exception { // 取消订单业务逻辑 System.out.println("订单1已过期准备取消"); } }; // 注册此定时任务(延迟时间为5秒,也就是说5秒后订单过期) timer.newTimeout(task1, 5, TimeUnit.SECONDS); // 定时任务 TimerTask task2 = new TimerTask() { public void run(Timeout timeout) throws Exception { // 取消订单业务逻辑 System.out.println("订单2已过期准备取消"); } }; // 注册此定时任务(延迟时间为3秒,也就是说3秒后订单过期) timer.newTimeout(task2, 3, TimeUnit.SECONDS); } }
Kelebihan: Data tidak mudah hilang dan pengembangan kluster mudah.
Kelemahan: Penyelenggaraan tambahan redis diperlukan.
Struktur data Redis Zset juga boleh mencapai kesan baris gilir tertunda, terutamanya menggunakan atribut skornya Redis menggunakan skor untuk meletakkan ahli dalam set daripada kecil kepada besar. menyusun. Tambahkan elemen pada baris gilir kelewatan melalui perintah zadd, dan tetapkan nilai skor untuk menunjukkan masa tamat tempoh elemen.
Pengguna meninjau delayqueue, mengisih elemen dan membandingkan masa minimum dengan masa semasa Jika kurang daripada masa semasa, ini bermakna kunci telah tamat tempoh dan dialih keluar.
@Configuration public class RedisListenerConfig { @Bean RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(connectionFactory); return container; } }
Kelebihan: Data tidak mudah hilang dan pengembangan kluster mudah.
Kelemahan: Kunci yang sama boleh digunakan berulang kali.
Gunakan middleware penjadualan tugas xxl-job, ScheduleX, Elastic-Job, dsb. untuk melaksanakannya apabila masa penjadualan tamat tempoh pesanan , pembatalan pelaksanaan tugas dicetuskan.
Contohnya, menggunakan pelaksanaan xxl-job, apabila pesanan dibuat, tugasan yang telah tamat tempoh diserahkan kepada pelayan xxl-job Berikut ialah kaedah pelaksana:
@Component public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener { public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) { super(listenerContainer); } @Override public void onMessage(Message message, byte[] pattern) { // 过期key,可以设置成订单号 String expiredKey = message.toString(); // 取消订单业务逻辑 System.out.println("订单 ---> " + expiredKey + " 已过期准备取消"); } }
Kelebihan: kuat. ketepatan masa dan sokongan untuk pengedaran.
Kelemahan: Pelaksanaan yang kompleks dan kos penyelenggaraan yang tinggi.
Menggunakan mesej tertunda daripada RocketMQ, RabbitMQ dan Kafka Selepas mesej dihantar ke pelayan baris gilir mesej, ia tidak akan dihantar serta-merta, tetapi akan ditangguhkan untuk tetap. masa berdasarkan atribut dalam mesej dan kemudian dihantar kepada pengguna.
Kod sampel untuk RocketMQ menghantar mesej tertunda adalah seperti berikut:
public void pollOrderQueue() { while (true) { Set<Tuple> set = jedis.zrangeWithScores(delayqueue, 0, 0); String value = ((Tuple) set.toArray()[0]).getElement(); int score = (int) ((Tuple) set.toArray()[0]).getScore(); int nowSecond = System.currentTimeMillis() / 1000); if (nowSecond >= score) { jedis.zrem(delayqueue, value); System.out.println(sdf.format(new Date()) + " removed key:" + value); } if (jedis.zcard(delayqueue) <= 0) { System.out.println(sdf.format(new Date()) + " zset empty "); return; } Thread.sleep(1000); } }
Langganan mesej tertunda RocketMQ adalah sama seperti langganan mesej biasa.
Kelebihan: cekap, mudah dikembangkan, menyokong pengedaran.
Kelemahan: Pelaksanaan yang kompleks dan kos penyelenggaraan yang tinggi.
Atas ialah kandungan terperinci Bagaimana untuk menggunakan Java untuk membatalkan pesanan yang tidak dibayar secara automatik?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!