面試題匯總06-場景題&線上問題排查&難點亮點
- 【一】場景題
- 【1】訂單到期關閉如何實現
- 【2】每天100w次登錄請求,4C8G機器如何做JVM調優?
- (1)問題描述和分析
- (2)堆內存設置
- (3)垃圾收集器選擇
- (4)各區大小設置
- (5)添加必要的日志
- 【3】如果你的業務量突然提升100倍QPS你會怎么做?
- 【二】線上問題排查
- 【1】RocketMQ消費堆積問題排查
- 【2】RT飆高問題排查過程
- 【3】數據庫死鎖問題排查過程
- (1)現象
- (2)背景介紹
- (3)死鎖日志
- (4)問題排查
- (5)索引分析
- (6)加鎖原理
- (7)解決方法
- 【4】數據庫死鎖問題排查問題2
- 【5】慢sql問題排查(聯合索引失效)
- (1)問題排查
- (2)問題解決
- 【6】線上sql優化的整體思路
- 【7】POI導致內存溢出排查(結果查詢數據導出)
- (1)問題描述
- (2)問題排查
- (3)問題解決
- 【8】頻繁FullGC問題排查
- (1)問題定位
- 【三】項目難點&亮點
- 【1】引入分布式鎖解決并發問題
- 【2】redis的多種使用案例
- 【3】easyExcel的多線程導出導入
- 【4】
【一】場景題
【1】訂單到期關閉如何實現
在電商、支付等系統中,一般都是先創建訂單(支付單),再給用戶一定的時間進行支付,如果沒有按時支付的話,就需要把之前的訂單(支付單)取消掉。這種類似的場景有很多,還有比如到期自動收貨、超時自動退款、下單后自動發送短信等等都是類似的業務問題。
訂單的到期關閉的實現有很多種方式,分別有:
1、被動關閉(不推薦)
2、定時任務(推薦,適合時間精確度要求不高的場景)
3、DelayQueue(不推薦,基于內存,無法持久化)
4、時間輪(不推薦,基于內存,無法持久化)
5、kafka(MQ 方案不推薦,大量無效調度)
6、RocketMQ延遲消息(MQ 方案不推薦,大量無效調度)
7、RabbitMQ死信隊列(MQ 方案不推薦,大量無效調度)
8、RabbitMQ插件(MQ 方案不推薦,大量無效調度)
9、Redis過期監聽(不推薦,容易丟消息)
10、Redis的ZSet(不推薦,可能會重復消費)
11、Redisson(推薦,可以用)
Redisson中定義了分布式延遲隊列RDelayedQueue,這是一種基于我們前面介紹過的zset結構實現的延時隊列,它允許以指定的延遲時長將元素放到目標隊列中。
其實就是在zset的基礎上增加了一個基于內存的延遲隊列。當我們要添加一個數據到延遲隊列的時候,redisson會把數據+超時時間放到zset中,并且起一個延時任務,當任務到期的時候,再去zset中把數據取出來,返回給客戶端使用。
?
定義一個Redisson客戶端:
?
@Configurationpublic class RedissonConfig { @Bean(destroyMethod="shutdown")
public RedissonClient redisson() throws IOException {Config config = new Config(); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); RedissonClient redisson = Redisson.create(config);return redisson;
}}
接下來,在想要使用延遲隊列的地方做如下方式:
?
org.redisson.api.RBlockingDeque;import org.redisson.api.RDelayedQueue;import org.redisson.api.RedissonClient;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.time.LocalDateTime;import java.time.format.DateTimeFormatter;import java.util.concurrent.TimeUnit;
@Componentpublic class RedissonOrderDelayQueue {@Autowired RedissonClient redisson;public void addTaskToDelayQueue(String orderId) { RBlockingDeque<String> blockingDeque = redisson.getBlockingDeque("orderQueue");RDelayedQueue<String> delayedQueue = redisson.getDelayedQueue(blockingDeque);System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "添加任務到延時隊列里面"); delayedQueue.offer(orderId, 3, TimeUnit.SECONDS); delayedQueue.offer(orderId, 6, TimeUnit.SECONDS); delayedQueue.offer(orderId, 9, TimeUnit.SECONDS); }public String getOrderFromDelayQueue() { RBlockingDeque<String> blockingDeque = redisson.getBlockingDeque("orderQueue"); RDelayedQueue<String> delayedQueue = redisson.getDelayedQueue(blockingDeque); String orderId = blockingDeque.take(); return orderId; }
}
使用offer方法將兩條延遲消息添加到RDelayedQueue中,使用take方法從RQueue中獲取消息,如果沒有消息可用,該方法會阻塞等待,直到消息到達。
我們使用 RDelayedQueue 的 offer 方法將元素添加到延遲隊列,并指定延遲的時間。當元素的延遲時間到達時,Redisson 會將元素從 RDelayedQueue 轉移到關聯的 RBlockingDeque 中。
使用 RBlockingDeque 的 take 方法從關聯的 RBlockingDeque 中獲取元素。這是一個阻塞操作,如果沒有元素可用,它會等待直到有元素可用。
所以,為了從延遲隊列中取出元素,使用 RBlockingDeque 的 take 方法,因為 Redisson 的 RDelayedQueue 實際上是通過轉移元素到關聯的 RBlockingDeque 來實現延遲隊列的。
【2】每天100w次登錄請求,4C8G機器如何做JVM調優?
(1)問題描述和分析
首先,我們需要問清楚,一天100W次的登錄,在一天內有沒有某個時段是高峰的?高峰期的QPS大概可以達到多少。
如果沒有高峰期,雖然100萬聽上去