分布式文件系統07-小文件系統的請求異步化高并發性能優化

小文件系統的請求異步化高并發性能優化

222_分布式圖片存儲系統中的高性能指的到底是什么?

重構系統架構,來實現一個高性能。然后就要做非常完善的一個測試,最后對這個系統做一個總結,說說后續我們還要做一些什么東西。另外,我還要給大家留一些作業,相當于是讓大家課后自己去做的,就不是完全拷貝我的代碼

高并發

前面已經通過Reactor模式實現了

高性能主要是兩塊

第一塊:客戶端現在是短連接,每次發送請求,都需要建立連接,然后斷開連接。站在客戶端的角度而言,發現每執行一次文件上傳和下載的操作,速度都很慢

第二塊:文件上傳,需要多副本上傳。一般來說,針對kafka,多副本的時候默認情況下只要寫成功一個副本,就返回了。另外其他的副本的寫都是異步慢慢來執行的,kafka采取的是副本pull數據的機制,只要在一個數據節點上寫成功數據,別的數據節點會主從從這個寫成功的數據節點上pull數據

Kafka,強調高性能,生產消息的行為都是盡快的可以完成

HDFS,不強調高性能,它主要針對的是幾個GB的大文件上傳到服務器上去,只要慢慢上傳就可以了,速度慢點無所謂,只要能上傳成功。所以,HDFS采用的是多個副本一定要依次上傳成功,才可以說是本次文件上傳成功了。所以,HDFS的上傳速度肯定是很慢的,因為它們根本不強調文件上傳過程的高性能。所以Kafka和HDFS的應用場景本身就不相同

高性能架構的重構

  • 短連接 -> 長連接;
  • 同步上傳多副本 -> 寫一個副本,其他副本在后臺慢慢的異步復制和拉取

這樣,文件上傳和文件下載,性能至少會提升好幾倍

223_回頭審視一下客戶端的短連接模式有哪些問題?

除了客戶端有NioClient以外,數據節點也有NioClient,因為他在進行數據節點擴縮容時,需要從其他的數據節點拷貝副本過來寫入本地,這個過程使用短連接也無所謂,因為這個過程都是后臺慢慢執行的,但是當然最好也是重構成長連接模式

224_初步實現用于進行網絡管理的NetworkManager組件

225_在NetworkManager中實現核心線程無限循環進行poll操作

NetworkManager
/*** 網絡連接管理器*/
public class NetworkManager {// 正在連接中public static final Integer CONNECTING = 1;// 已經建立連接public static final Integer CONNECTED = 2;// 多路復用Selectorprivate Selector selector;// 所有的連接private Map<String, SocketChannel> connections;// 每個數據節點的連接狀態private Map<String, Integer> connectState;// 等待建立連接的機器private ConcurrentLinkedQueue<Host> waitingConnectHosts;public NetworkManager() {try {this.selector = Selector.open();} catch (IOException e) {e.printStackTrace();}this.connections = new ConcurrentHashMap<String, SocketChannel>();this.connectState = new ConcurrentHashMap<String, Integer>();this.waitingConnectHosts = new ConcurrentLinkedQueue<Host>();new NetworkPollThread().start();}/*** 嘗試連接到數據節點的端口上去*/public void maybeConnect(String hostname, Integer nioPort) throws Exception {synchronized(this) {if(!connectState.containsKey(hostname)) {connectState.put(hostname, CONNECTING);waitingConnectHosts.offer(new Host(hostname, nioPort)); }while(connectState.get(hostname).equals(CONNECTING)) {wait(100);}}}/*** 嘗試把排隊中的機器發起連接的請求*/private void tryConnect() {try {Host host = null;SocketChannel channel = null;while((host = waitingConnectHosts.poll()) != null) {channel = SocketChannel.open();  channel.configureBlocking(false);  channel.connect(new InetSocketAddress(host.hostname, host.nioPort)); channel.register(selector, SelectionKey.OP_CONNECT);  }} catch (Exception e) {e.printStackTrace();}}// 網絡連接的核心線程class NetworkPollThread extends Thread {@Overridepublic void run() {while(true) {tryConnect();}}}// 代表了一臺機器class Host {String hostname;Integer nioPort;public Host(String hostname, Integer nioPort) {this.hostname = hostname;this.nioPort = nioPort;}}}

226_在無限循環的poll方法中完成網絡連接的建立

public class NetworkManager {// 正在連接中public static final Integer CONNECTING = 1;// 已經建立連接public static final Integer CONNECTED = 2;// 網絡poll操作的超時時間public static final Long POLL_TIMEOUT = 500L; // 多路復用Selectorprivate Selector selector;// 所有的連接private Map<String, SocketChannel> connections;// 每個數據節點的連接狀態private Map<String, Integer> connectState;// 等待建立連接的機器private ConcurrentLinkedQueue<Host> waitingConnectHosts;public NetworkManager() {try {this.selector = Selector.open();} catch (IOException e) {e.printStackTrace();}this.connections = new ConcurrentHashMap<String, SocketChannel>();this.connectState = new ConcurrentHashMap<String, Integer>();this.waitingConnectHosts = new ConcurrentLinkedQueue<Host>();new NetworkPollThread().start();}/*** 嘗試連接到數據節點的端口上去*/public void maybeConnect(String hostname, Integer nioPort) throws Exception {synchronized(this) {if(!connectState.containsKey(hostname)) {connectState.put(hostname, CONNECTING);waitingConnectHosts.offer(new Host(hostname, nioPort)); }while(connectState.get(hostname).equals(CONNECTING)) {wait(100);}}}// 網絡連接的核心線程class NetworkPollThread extends Thread {@Overridepublic void run() {while(true) {tryConnect();poll();}}/*** 嘗試把排隊中的機器發起連接的請求*/private void tryConnect() {try {Host host = null;SocketChannel channel = null;while((host = waitingConnectHosts.poll()) != null) {channel = SocketChannel.open();  channel.configureBlocking(false);  channel.connect(new InetSocketAddress(host.hostname, host.nioPort)); channel.register(selector, SelectionKey.OP_CONNECT);  }} catch (Exception e) {e.printStackTrace();}}/*** 嘗試完成網絡連接、請求發送、響應讀取*/private void poll() {SocketChannel channel = null;try {int selectedKeys = selector.select(500);   if(selectedKeys <= 0) {return;}Iterator<SelectionKey> keysIterator = selector.selectedKeys().iterator();  while(keysIterator.hasNext()){  SelectionKey key = (SelectionKey) keysIterator.next();  keysIterator.remove();  // 如果是網絡連接操作if(key.isConnectable()){  channel = (SocketChannel) key.channel();if(channel.isConnectionPending()){  while(!channel.finishConnect()) {Thread.sleep(100); }}   System.out.println("完成與服務端的連接的建立......"); InetSocketAddress remoteAddress = (InetSocketAddress)channel.getRemoteAddress();connectState.put(remoteAddress.getHostName(), CONNECTED);connections.put(remoteAddress.getHostName(), channel);}}} catch (Exception e) {e.printStackTrace();if(channel != null) {try {channel.close();} catch (IOException e1) {e1.printStackTrace();}}}}}// 代表了一臺機器class Host {String hostname;Integer nioPort;public Host(String hostname, Integer nioPort) {this.hostname = hostname;this.nioPort = nioPort;}}}

227_客戶端的核心業務方法對要發送的請求進行封裝

228_將封裝好的請求放入NetworkManager的請求隊列中

229_如何實現異步發送請求以及同步等待響應兩個接口

230_對每個數據節點獲取一個請求緩存起來等待發送

231_在核心的poll方法中將每個機器暫存等待的請求發送出去

232_在核心的poll方法中對機器返回的響應進行讀取

拿到響應

客戶端將請求發出以后,就每隔100ms輪詢一次,有沒有響應結果返回回來

233_客戶端建立連接的過程中異常了該如何返回響應?

234_客戶端發送請求過程中異常了該如何返回響應?

/*** 發送請求*/private void sendRequest(SelectionKey key, SocketChannel channel) {InetSocketAddress remoteAddress = null;try {remoteAddress = (InetSocketAddress) channel.getRemoteAddress();String hostname = remoteAddress.getHostName();// 獲取要發送到這臺機器的請求的數據NetworkRequest request = toSendRequests.get(hostname);ByteBuffer buffer = request.getBuffer();// 將請求發送到對方機器上去channel.write(buffer);while (buffer.hasRemaining()) {channel.write(buffer);}System.out.println("本次請求發送完畢......");key.interestOps(SelectionKey.OP_READ);} catch (Exception e) {e.printStackTrace();// 發送失敗,就取消關注OP_WRITE事件key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);if (remoteAddress != null) {String hostname = remoteAddress.getHostName();NetworkRequest request = toSendRequests.get(hostname);if (request.needResponse()) {NetworkResponse response = new NetworkResponse();response.setHostname(hostname);response.setRequestId(request.getId());// 請求發送失敗,則客戶端手動構造一個響應response.setError(true);finishedResponses.put(request.getId(), response);} else {toSendRequests.remove(hostname);}}}}

完整代碼

NioClient
*** 客戶端的一個NIOClient,負責跟數據節點進行網絡通信*/
public class NioClient {private NetworkManager networkManager;public NioClient() {this.networkManager = new NetworkManager();}/*** 發送一個文件過去*/public Boolean sendFile(String hostname, int nioPort, byte[] file, String filename, long fileLength) {  // 先根據hostname來檢查一下,跟對方機器的連接是否建立好了// 沒有建立好,那么就直接在此建立連接; 建立好連接后,就把連接給緩存起來,以備下次使用try {// 如果此時還沒跟那個數據節點建立好連接if(!networkManager.maybeConnect(hostname, nioPort)) {return false;}NetworkRequest request = createSendFileRequest(hostname, nioPort, file, filename, fileLength);networkManager.sendRequest(request); NetworkResponse response = networkManager.waitResponse(request.getId());if(response.error()) {// 請求發送失敗,客戶端自己構造的response,并將response.error 設置為truereturn false;}ByteBuffer buffer = response.getBuffer();String responseStatus = new String(buffer.array(), 0, buffer.remaining());System.out.println("收到" + hostname + "的響應:" + responseStatus);return responseStatus.equals(NetworkResponse.RESPONSE_SUCCESS);} catch (Exception e) {e.printStackTrace(); }return false;}/*** 構建一個發送文件的網絡請求*/private NetworkRequest createSendFileRequest(String hostname, Integer nioPort, byte[] file, String filename, long fileLength) {NetworkRequest request = new NetworkRequest();ByteBuffer buffer = ByteBuffer.allocate(NetworkRequest.REQUEST_TYPE + NetworkRequest.FILENAME_LENGTH + filename.getBytes().length + NetworkRequest.FILE_LENGTH + (int)fileLength); buffer.putInt(NetworkRequest.REQUEST_SEND_FILE); buffer.putInt(filename.getBytes().length); buffer.put(filename.getBytes()); buffer.putLong(fileLength); buffer.put(file);buffer.rewind(); request.setId(UUID.randomUUID().toString()); request.setHostname(hostname); request.setNioPort(nioPort); request.setBuffer(buffer); request.setNeedResponse(true); return request;}}

NetworkManager
/*** 網絡連接管理器*/
public class NetworkManager {// 正在連接中public static final Integer CONNECTING = 1;// 已經建立連接public static final Integer CONNECTED = 2;// 斷開連接public static final Integer DISCONNECTED = 3;// 響應狀態:成功public static final Integer RESPONSE_SUCCESS = 1;// 響應狀態:失敗public static final Integer RESPONSE_FAILURE = 2;// 網絡poll操作的超時時間public static final Long POLL_TIMEOUT = 500L;// 多路復用Selectorprivate Selector selector;// 所有的連接private Map<String, SelectionKey> connections;// 每個數據節點的連接狀態private Map<String, Integer> connectState;// 等待建立連接的機器private final ConcurrentLinkedQueue<Host> waitingConnectHosts;// 排隊等待發送的網絡請求private Map<String, ConcurrentLinkedQueue<NetworkRequest>> waitingRequests;// 馬上準備要發送的網絡請求private Map<String, NetworkRequest> toSendRequests;// 已經完成請求的響應private Map<String, NetworkResponse> finishedResponses;public NetworkManager() {try {this.selector = Selector.open();} catch (IOException e) {e.printStackTrace();}this.connections = new ConcurrentHashMap<String, SelectionKey>();this.connectState = new ConcurrentHashMap<String, Integer>();this.waitingConnectHosts = new ConcurrentLinkedQueue<Host>();this.waitingRequests = new ConcurrentHashMap<String, ConcurrentLinkedQueue<NetworkRequest>>();this.toSendRequests = new ConcurrentHashMap<String, NetworkRequest>();this.finishedResponses = new ConcurrentHashMap<String, NetworkResponse>();new NetworkPollThread().start();}/*** 嘗試連接到數據節點的端口上去*/public Boolean maybeConnect(String hostname, Integer nioPort) {synchronized (this) {if (!connectState.containsKey(hostname) ||connectState.get(hostname).equals(DISCONNECTED)) {connectState.put(hostname, CONNECTING);waitingConnectHosts.offer(new Host(hostname, nioPort));}while (connectState.get(hostname).equals(CONNECTING)) {try {wait(100);} catch (InterruptedException e) {e.printStackTrace();}}if (connectState.get(hostname).equals(DISCONNECTED)) {return false;}return true;}}/*** 發送網絡請求** @param request*/public void sendRequest(NetworkRequest request) {ConcurrentLinkedQueue<NetworkRequest> requestQueue =waitingRequests.get(request.getHostname());requestQueue.offer(request);}/*** 等待指定請求的響應*/public NetworkResponse waitResponse(String requestId) throws Exception {NetworkResponse response = null;while ((response = finishedResponses.get(requestId)) == null) {Thread.sleep(100);}toSendRequests.remove(response.getHostname());finishedResponses.remove(requestId);return response;}// 網絡連接的核心線程class NetworkPollThread extends Thread {@Overridepublic void run() {while (true) {tryConnect();prepareRequests();poll();}}/*** 嘗試把排隊中的機器發起連接的請求*/private void tryConnect() {Host host = null;SocketChannel channel = null;while ((host = waitingConnectHosts.poll()) != null) {try {channel = SocketChannel.open();channel.configureBlocking(false);channel.connect(new InetSocketAddress(host.hostname, host.nioPort));channel.register(selector, SelectionKey.OP_CONNECT);} catch (Exception e) {e.printStackTrace();connectState.put(host.hostname, DISCONNECTED);}}}/*** 準備好要發送的請求*/private void prepareRequests() {for (String hostname : waitingRequests.keySet()) {// 看一下這臺機器當前是否還沒有請求馬上就要發送出去了ConcurrentLinkedQueue<NetworkRequest> requestQueue =waitingRequests.get(hostname);if (!requestQueue.isEmpty() && !toSendRequests.containsKey(hostname)) {// 對這臺機器獲取一個派對的請求出來NetworkRequest request = requestQueue.poll();// 將這個請求暫存起來,接下來 就可以等待發送出去toSendRequests.put(hostname, request);// 讓這臺機器對應的連接關注的事件為OP_WRITESelectionKey key = connections.get(hostname);key.interestOps(SelectionKey.OP_WRITE);}}}/*** 嘗試完成網絡連接、請求發送、響應讀取*/private void poll() {SocketChannel channel = null;try {int selectedKeys = selector.select(500);if (selectedKeys <= 0) {return;}Iterator<SelectionKey> keysIterator = selector.selectedKeys().iterator();while (keysIterator.hasNext()) {SelectionKey key = (SelectionKey) keysIterator.next();keysIterator.remove();channel = (SocketChannel) key.channel();// 如果是網絡連接操作if (key.isConnectable()) {// 建立連接finishConnect(key, channel);} else if (key.isWritable()) {// 發送請求sendRequest(key, channel);} else if (key.isReadable()) {// 接收響應readResponse(key, channel);}}} catch (Exception e) {e.printStackTrace();if (channel != null) {try {channel.close();} catch (IOException e1) {e1.printStackTrace();}}}}/*** 完成跟機器的連接*/private void finishConnect(SelectionKey key, SocketChannel channel) {InetSocketAddress remoteAddress = null;try {remoteAddress = (InetSocketAddress) channel.getRemoteAddress();if (channel.isConnectionPending()) {while (!channel.finishConnect()) {Thread.sleep(100);}}System.out.println("完成與服務端的連接的建立......");waitingRequests.put(remoteAddress.getHostName(),new ConcurrentLinkedQueue<NetworkRequest>());connections.put(remoteAddress.getHostName(), key);// 將連接狀態置為:已連接connectState.put(remoteAddress.getHostName(), CONNECTED);} catch (Exception e) {e.printStackTrace();if (remoteAddress != null) {connectState.put(remoteAddress.getHostName(), DISCONNECTED);}}}/*** 發送請求*/private void sendRequest(SelectionKey key, SocketChannel channel) {InetSocketAddress remoteAddress = null;try {remoteAddress = (InetSocketAddress) channel.getRemoteAddress();String hostname = remoteAddress.getHostName();// 獲取要發送到這臺機器的請求的數據NetworkRequest request = toSendRequests.get(hostname);ByteBuffer buffer = request.getBuffer();// 將請求發送到對方機器上去channel.write(buffer);while (buffer.hasRemaining()) {channel.write(buffer);}System.out.println("本次請求發送完畢......");key.interestOps(SelectionKey.OP_READ);} catch (Exception e) {e.printStackTrace();// 發送失敗,就取消關注OP_WRITE事件key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);if (remoteAddress != null) {String hostname = remoteAddress.getHostName();NetworkRequest request = toSendRequests.get(hostname);if (request.needResponse()) {NetworkResponse response = new NetworkResponse();response.setHostname(hostname);response.setRequestId(request.getId());// 請求發送失敗,則客戶端手動構造一個響應response.setError(true);finishedResponses.put(request.getId(), response);} else {toSendRequests.remove(hostname);}}}}/*** 讀取響應信息*/private void readResponse(SelectionKey key, SocketChannel channel) throws Exception {InetSocketAddress remoteAddress = (InetSocketAddress) channel.getRemoteAddress();String hostname = remoteAddress.getHostName();NetworkRequest request = toSendRequests.get(hostname);NetworkResponse response = null;if (request.getRequestType().equals(NetworkRequest.REQUEST_SEND_FILE)) {response = readSendFileResponse(request.getId(), hostname, channel);}key.interestOps(key.interestOps() & ~SelectionKey.OP_READ);// 如果發送請求時,明確表示需要返回值if (request.needResponse()) {finishedResponses.put(request.getId(), response);} else {toSendRequests.remove(hostname);}}/*** 讀取上傳文件的響應*/private NetworkResponse readSendFileResponse(String requestId,String hostname, SocketChannel channel) throws Exception {ByteBuffer buffer = ByteBuffer.allocate(1024);channel.read(buffer);buffer.flip();NetworkResponse response = new NetworkResponse();response.setRequestId(requestId);response.setHostname(hostname);response.setBuffer(buffer);response.setError(false);return response;}}// 代表了一臺機器class Host {String hostname;Integer nioPort;public Host(String hostname, Integer nioPort) {this.hostname = hostname;this.nioPort = nioPort;}}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/92261.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/92261.shtml
英文地址,請注明出處:http://en.pswp.cn/web/92261.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【C#補全計劃:類和對象(十)】密封

一、密封類1. 關鍵字&#xff1a;sealed2. 作用&#xff1a;使類無法再被繼承&#xff1b;在面向對象設計中&#xff0c;密封類的主要作用是不允許最底層子類被繼承&#xff0c;可以保證程序的規范性、安全性3. 使用&#xff1a;using System;namespace Sealed {// 使用sealed關…

【視覺識別】Ubuntu 22.04 上安裝和配置 TigerVNC 魯班貓V5

系列文章目錄 文章目錄系列文章目錄前言一、問題現象二、安裝和配置步驟1.引入庫2.安裝完整組件3.修改 ~/.vnc/xstartup4. 設置權限5. 設置開機自啟&#xff08;Systemd 服務&#xff09;總結前言 開發平臺&#xff1a;魯班貓V5 RK3588 系統版本&#xff1a;Ubuntu 22.04 一、…

模擬-38.外觀數列-力扣(LeetCode)

一、題目解析1、替換的方法&#xff1a;“33”用“23”替換&#xff0c;即找到相同的數&#xff0c;前一位為相同數的數量&#xff0c;后一位為相同的數2、給定n&#xff0c;需要返回外觀數列的第n個元素二、算法原理由于需要統計相同元素的數目&#xff0c;所以可以使用雙指針…

垃圾桶滿溢識別準確率↑32%:陌訊多模態融合算法實戰解析

原創聲明本文為原創技術解析文章&#xff0c;涉及的技術參數與架構設計均參考自《陌訊技術白皮書》&#xff0c;轉載請注明來源。一、行業痛點&#xff1a;智慧環衛中的識別難題隨著智慧城市建設推進&#xff0c;垃圾桶滿溢識別作為智慧環衛的核心環節&#xff0c;面臨多重技術…

掃地機器人的幾種語音控制芯片方案介紹

?掃地機器人語音控制芯片方案介紹在智能家居領域&#xff0c;掃地機器人的智能化程度不斷提升&#xff0c;語音控制功能成為提升用戶體驗的關鍵因素。以下為您介紹幾款常用于掃地機器人語音控制的芯片方案。WT2606B 芯片方案性能優勢&#xff1a;基于先進的 RISC - V 32 位開源…

快速開發實踐

基于后端項目的前端開發實踐記錄 &#x1f4cb; 項目概述 項目名稱: 比特奧定制報表系統 技術棧: Vue 3 Element Plus Vite (前端) Spring Boot (后端) 開發模式: 前后端分離 項目結構: 單體倉庫包含前后端代碼 &#x1f3d7;? 項目架構分析 目錄結構設計 bitao-defined_re…

NFC 三大模式對比

以前以為nfc只是點對點通訊&#xff0c;沒想到現在nfc的功能很強大NFC 三大模式對比&#xff08;回顧&#xff09;模式作用手機是...Reader 模式讀取卡、標簽內容主動設備&#xff08;讀卡器&#xff09;Card Emulation 模式模擬公交卡/門禁卡/銀行卡被動設備&#xff08;卡&am…

JSON、JSONObject、JSONArray詳細介紹及其應用方式

第一部分&#xff1a;什么是JSON?&#x1f31f;比喻&#xff1a;JSON 是「快遞公司統一的 “通用快遞單”」&#x1f4a1;場景代入你想給朋友寄生日禮物&#xff08;比如一臺 “游戲機”&#xff09;&#xff0c;這臺游戲機有自己的屬性&#xff1a;名稱&#xff1a;"游戲…

Linux系統編程--權限管理

權限管理第二講 權限管理1. Shell命令以及運行原理1.1 知識引入1.2 概念介紹1.3 具體示例2. Linux權限問題2.1 權限概念2.2 用戶分類2.3 切換用戶2.4 用戶提權2.5 文件權限管理2.5.1 文件訪問者的分類&#xff08;角色&#xff09;2.5.2 文件類型和訪問權限&#xff08;事物屬性…

【智能硬件】X86和ARM架構的區別

詳細解釋X86架構和ARM架構之間的區別以及它們各自的特點。X86 架構定義與歷史定義&#xff1a;X86是一種計算機處理器體系結構&#xff0c;最初由英特爾公司開發。它是一系列指令集的集合體。歷史&#xff1a;最早的X86架構是Intel 8086處理器&#xff0c;在1978年發布。后續發…

玳瑁的嵌入式日記D13-0806(C語言)

指針1.指針指針 就是地址(地址就是內存單元的編號)指針變量 (結合語境) eg&#xff1a;定義一個指針指針這一類數據 --- 數據類型 --- 指針類型 (1).指針 是什么 (2).指針類型 int a; //int數據類型 a是int型變量 //a的空間 想來存儲 整型數據 2.指針的定義 基類型 * 指針變量名…

密碼學基礎知識總結

密碼學基礎知識總結 一、Base編碼 1. Base系列特征 編碼類型字符集特征Base160-9, A-F密文長度偶數Base32A-Z, 2-7包含數字2-7Base64a-z,0-9,,/,密文長度是8的倍數Base36A-Z,0-9僅支持整數加密Base910-9,a-z,A-Z,特殊符號高密度編碼Base100Emoji表情表情符號組成 2. 典型題型…

PostgreSQL 中 pg_wal文件過多過大的清理方法及關鍵注意事項的總結

PostgreSQL 中 pg_wal文件過多過大的清理方法及關鍵注意事項的總結 以下是針對 PostgreSQL 中 pg_wal 文件過多過大的清理方法及關鍵注意事項的總結 一、安全清理 WAL 文件的完整流程 1. 確認數據庫和備份完整性 備份驗證&#xff1a;確保最近的物理備份&#xff08;如 pg_base…

Django事務支持

1.事務概念 事務是一組不可分割的操作序列&#xff0c;這些操作要么全部執行&#xff0c;要么全部不執行。事務具有四個關鍵屬性&#xff0c;通常稱為 ACID 特性&#xff1a; 原子性&#xff08;Atomicity&#xff09;&#xff1a;事務是一個不可分割的工作單位&#xff0c;事務…

<form> + <iframe> 方式下載大文件的機制

使用 <form> <iframe> 方式下載大文件的機制之所以穩定&#xff0c;核心在于其?分塊傳輸?和?瀏覽器沙箱隔離?設計。以下是技術原理詳解&#xff1a; 一、底層工作機制 ?分塊傳輸協議? 表單提交后&#xff0c;服務器按 Transfer-Encoding: chunked 分塊返回數…

Python--OCR(2)

一、明確 OCR 任務邊界首先定義 OCR 系統的核心目標&#xff1a;場景&#xff1a;印刷體&#xff08;如文檔、發票&#xff09;/ 手寫體&#xff08;如筆記&#xff09;/ 特定場景&#xff08;如車牌、身份證&#xff09;輸入&#xff1a;圖像格式&#xff08;JPG/PNG&#xff…

基于Django的計算機資源爬蟲及可視化系統的設計與實現

文章目錄有需要本項目的代碼或文檔以及全部資源&#xff0c;或者部署調試可以私信博主一、項目背景二、項目目標三、系統架構與技術選型四、系統功能模塊五、應用場景與價值六、項目特色與創新點七、總結每文一語有需要本項目的代碼或文檔以及全部資源&#xff0c;或者部署調試…

SH3001六軸傳感器應用(二)(IIC驅動開發)

一、前言我這邊使用的開發板原本已經做好了該sensor的驅動&#xff0c;但是使用過程中發現&#xff0c;原始驅動sensor是通過事件的方式上報的&#xff0c;加速度和陀螺儀數據并不同步&#xff0c;不滿足使用要求&#xff0c;只有重新寫一個iic的驅動&#xff0c;進行sensor數據…

面試題:基礎的sql命令

基礎的 SQL 命令主要用于對數據庫進行查詢、新增、修改、刪除等操作&#xff0c;可分為以下幾類&#xff1a;一、數據查詢&#xff08;SELECT&#xff09;用于從表中獲取數據&#xff0c;是最常用的命令。 基本語法&#xff1a;SELECT 列名1, 列名2... FROM 表名 WHERE 條件;示…

Leetcode-3488距離最小相等元素查詢

依舊二分&#xff0c;鏈接如下3488. 距離最小相等元素查詢 看題目是個循環數組&#xff0c;記得當時做過一道什么題也是循環數組&#xff0c;就想著直接數組復制一下&#xff0c;然后跟上一道題一樣&#xff0c;用hashmap來存儲value的值以及value對應下標的vector。 和靈神的…