分布式選舉算法<一> Bully算法

分布式選舉算法詳解:Bully算法

引言

在分布式系統中,節點故障是不可避免的。當主節點(Leader)發生故障時,系統需要快速選舉出新的主節點來保證服務的連續性。Bully算法是一種經典的分布式選舉算法,以其簡單高效的特點被廣泛應用于各種分布式系統中。

什么是Bully算法?

Bully算法是一種基于優先級的分布式選舉算法。每個節點都有一個唯一的ID,ID值越大的節點優先級越高。當主節點故障時,優先級最高的節點將成為新的主節點。

核心思想

  • “強者為王”:ID最大的節點自動成為主節點
  • 主動選舉:節點發現主節點故障時,主動發起選舉
  • 快速收斂:選舉過程簡單,收斂速度快

算法流程

1. 選舉觸發條件

選舉在以下情況下觸發:

  • 節點發現主節點無響應
  • 新節點加入系統
  • 節點從故障中恢復

2. 選舉過程

節點A (ID=1)    節點B (ID=2)    節點C (ID=3)    節點D (ID=4)|              |              |              ||-- Election -->|              |              ||              |-- Election -->|              ||              |              |-- Election -->||              |              |              ||              |              |<-- Victory ---||              |<-- Victory ---|              ||<-- Victory ---|              |              |

詳細步驟:

  1. 發起選舉:節點A發現主節點故障,向所有ID大于自己的節點發送Election消息
  2. 響應檢查:如果收到響應,說明有更高優先級的節點存在
  3. 等待勝利:如果沒有收到響應,等待Victory消息
  4. 宣布勝利:如果自己是最高優先級,向所有節點發送Victory消息
  5. 成為主節點:收到Victory消息的節點更新主節點信息

3. 消息類型

  • Election:發起選舉請求
  • Victory:宣布選舉勝利
  • Ping:心跳檢測
  • Pong:心跳響應

算法特點

優點

  1. 簡單高效:算法邏輯簡單,易于實現和理解

    • 只需要比較節點ID大小
    • 不需要復雜的狀態機
    • 代碼實現直觀,調試容易
  2. 快速收斂:選舉過程快速,通常只需要幾輪消息交換

    • 最多需要O(n)輪消息交換
    • 不需要多輪投票過程
    • 適合對響應時間要求高的場景
  3. 確定性:總是選舉出ID最大的活躍節點

    • 結果可預測,便于系統設計
    • 避免了隨機性帶來的不確定性
    • 便于負載均衡策略制定
  4. 容錯性:能夠處理節點故障和網絡分區

    • 自動檢測節點故障
    • 支持部分網絡分區場景
    • 故障恢復后能重新選舉

缺點

  1. 消息開銷大:選舉過程中需要發送大量消息

    • 每個節點都要向所有更高優先級節點發送消息
    • 消息數量為O(n2)級別
    • 在大規模集群中開銷顯著
  2. 不公平:總是選擇ID最大的節點,可能導致負載不均

    • 高優先級節點承擔更多責任
    • 低優先級節點資源利用率低
    • 不利于負載分散
  3. 網絡敏感:對網絡延遲和丟包比較敏感

    • 消息丟失會導致選舉失敗
    • 網絡延遲影響選舉速度
    • 需要額外的可靠性機制
  4. 活鎖風險:在某些情況下可能出現選舉沖突

    • 多個節點同時發起選舉
    • 消息丟失導致超時重試
    • 可能形成無限循環

常見問題與解決方案

1. 腦裂問題(Split Brain)

問題描述:
網絡分區導致系統出現多個主節點,每個分區都認為自己是主節點。

場景示例:

網絡分區前:
節點A(1) -- 節點B(2) -- 節點C(3) -- 節點D(4)Leader: 節點D網絡分區后:
分區1: 節點A(1) -- 節點B(2)    分區2: 節點C(3) -- 節點D(4)Leader: 節點B                Leader: 節點D

解決方案:

方案1:多數派機制
class BullyNode:def __init__(self, node_id, all_nodes):self.node_id = node_idself.all_nodes = all_nodesself.quorum_size = len(all_nodes) // 2 + 1  # 多數派閾值def declare_victory(self):"""只有獲得多數派支持才能成為主節點"""responses = self.collect_victory_responses()if len(responses) >= self.quorum_size:self.become_leader()else:self.wait_for_quorum()
方案2:租約機制(Lease)
class LeaseBasedBullyNode:def __init__(self, node_id, all_nodes):self.node_id = node_idself.lease_duration = 30  # 租約30秒self.lease_expiry = 0def renew_lease(self):"""定期續約,確保主節點有效性"""if time.time() > self.lease_expiry:self.start_election()else:self.broadcast_lease_renewal()
方案3:時間戳機制
class TimestampBasedBullyNode:def __init__(self, node_id, all_nodes):self.node_id = node_idself.term_number = 0  # 任期號def start_election(self):"""使用任期號避免腦裂"""self.term_number += 1self.broadcast_election_with_term(self.term_number)def receive_victory(self, leader_id, term):"""只接受更高任期的主節點"""if term >= self.term_number:self.leader_id = leader_idself.term_number = term

2. 活鎖問題(Live Lock)

問題描述:
多個節點同時發起選舉,導致選舉過程無限循環。

深入分析:

活鎖問題的核心在于并發選舉觸發消息傳遞的時序問題。即使只向ID更大的節點發送消息,仍然可能出現以下情況:

場景1:并發選舉觸發
時間線分析:
T1: 節點A(1) 發現主節點故障,發起選舉
T2: 節點B(2) 同時發現主節點故障,發起選舉  
T3: 節點C(3) 同時發現主節點故障,發起選舉
場景2:消息傳遞時序問題
詳細時序:
T1: A向B發送Election消息
T2: B向C發送Election消息  
T3: A等待B的響應(但B正在處理自己的選舉)
T4: B等待C的響應
T5: C沒有更高優先級節點,C成為主節點
T6: C向B發送Victory消息
T7: B向A發送Victory消息問題:如果T6或T7的消息丟失了怎么辦?
場景3:網絡延遲和消息丟失
更復雜的場景:
節點A(1) -- 網絡延遲 -- 節點B(2) -- 網絡延遲 -- 節點C(3)T1: A發起選舉,向B發送消息
T2: B發起選舉,向C發送消息(A的消息還沒到)
T3: C成為主節點,向B發送Victory
T4: B收到C的Victory,但A還在等待B的響應
T5: A超時,重新發起選舉
T6: 循環開始...

活鎖的根本原因:

  1. 并發檢測:多個節點同時檢測到主節點故障
  2. 網絡不確定性:消息延遲、丟失、亂序
  3. 超時重試:超時機制觸發重新選舉
  4. 缺乏協調:沒有全局的選舉協調機制

解決方案:

方案1:隨機退避
import random
import timeclass BullyNode:def start_election(self):"""隨機退避避免沖突"""if self.election_in_progress:return# 隨機延遲,減少沖突delay = random.uniform(0, 2.0)time.sleep(delay)self.election_in_progress = Trueself.broadcast_election()
方案2:優先級隊列
class PriorityBasedBullyNode:def __init__(self, node_id, all_nodes):self.node_id = node_idself.election_queue = []def start_election(self):"""按優先級順序發起選舉"""if not self.election_queue:self.election_queue = sorted(self.all_nodes, reverse=True)if self.election_queue[0] == self.node_id:self.declare_victory()else:self.wait_for_higher_priority()
方案3:狀態機機制
from enum import Enumclass NodeState(Enum):FOLLOWER = "follower"CANDIDATE = "candidate"LEADER = "leader"class StateMachineBullyNode:def __init__(self, node_id, all_nodes):self.state = NodeState.FOLLOWERself.election_timeout = 5def start_election(self):"""狀態機控制選舉流程"""if self.state == NodeState.FOLLOWER:self.state = NodeState.CANDIDATEself.broadcast_election()self.start_election_timer()def handle_election_timeout(self):"""選舉超時處理"""if self.state == NodeState.CANDIDATE:self.state = NodeState.FOLLOWERself.start_election()  # 重新發起選舉

3. 消息丟失問題

問題描述:
網絡不穩定導致選舉消息丟失,影響選舉結果。

具體影響:

  • Election消息丟失:導致選舉無法正常進行
  • Victory消息丟失:導致節點無法確認主節點
  • 心跳消息丟失:導致誤判節點故障

解決方案:

方案1:確認機制
class ReliableBullyNode:def send_election_message(self, target_node):"""發送選舉消息并等待確認"""message_id = self.generate_message_id()self.send_message(target_node, "Election", message_id)# 等待確認if not self.wait_for_ack(message_id, timeout=3):self.retry_send(target_node, message_id)def send_ack(self, message_id):"""發送確認消息"""self.send_message(self.sender, "ACK", message_id)
方案2:重傳機制
class RetryBullyNode:def __init__(self, node_id, all_nodes):self.pending_messages = {}  # 待確認的消息self.max_retries = 3def send_with_retry(self, target, message, max_retries=3):"""帶重試的消息發送"""for attempt in range(max_retries):if self.send_message(target, message):return Truetime.sleep(2 ** attempt)  # 指數退避return False

4. 性能問題

問題描述:
選舉過程中消息開銷大,影響系統性能。

性能瓶頸分析:

  • 消息數量:O(n2)的消息復雜度
  • 網絡帶寬:大量并發消息占用帶寬
  • CPU開銷:消息處理消耗CPU資源
  • 延遲影響:選舉期間服務可能暫停

解決方案:

方案1:批量消息
class BatchBullyNode:def broadcast_election(self):"""批量發送選舉消息"""message = self.create_election_message()batch_size = 10for i in range(0, len(self.all_nodes), batch_size):batch = self.all_nodes[i:i+batch_size]self.send_batch_message(batch, message)
方案2:異步處理
import asyncioclass AsyncBullyNode:async def start_election_async(self):"""異步選舉處理"""tasks = []for node_id in self.higher_priority_nodes:task = asyncio.create_task(self.send_election_async(node_id))tasks.append(task)responses = await asyncio.gather(*tasks, return_exceptions=True)return [r for r in responses if not isinstance(r, Exception)]
方案3:緩存機制
class CachedBullyNode:def __init__(self, node_id, all_nodes):self.node_cache = {}  # 節點狀態緩存self.cache_ttl = 30   # 緩存30秒def get_node_status(self, node_id):"""獲取節點狀態(帶緩存)"""if node_id in self.node_cache:cache_time, status = self.node_cache[node_id]if time.time() - cache_time < self.cache_ttl:return statusstatus = self.ping_node(node_id)self.node_cache[node_id] = (time.time(), status)return status

最佳實踐

1. 監控與告警

class MonitoredBullyNode:def __init__(self, node_id, all_nodes):self.metrics = {'election_count': 0,'election_duration': [],'message_loss_rate': 0.0}def record_election_metrics(self, duration):"""記錄選舉指標"""self.metrics['election_count'] += 1self.metrics['election_duration'].append(duration)# 告警:選舉過于頻繁if self.metrics['election_count'] > 10:self.alert("Election frequency too high")

2. 配置管理

class ConfigurableBullyNode:def __init__(self, node_id, all_nodes, config):self.election_timeout = config.get('election_timeout', 5)self.heartbeat_interval = config.get('heartbeat_interval', 1)self.max_retries = config.get('max_retries', 3)self.quorum_size = config.get('quorum_size', len(all_nodes) // 2 + 1)

3. 日志記錄

import loggingclass LoggedBullyNode:def __init__(self, node_id, all_nodes):self.logger = logging.getLogger(f"bully_node_{node_id}")def log_election_event(self, event_type, details):"""記錄選舉事件"""self.logger.info(f"Election event: {event_type} - {details}")def log_error(self, error_type, details):"""記錄錯誤"""self.logger.error(f"Error: {error_type} - {details}")

實際應用場景

1. 數據庫集群

  • MongoDB:使用類似Bully的算法進行主節點選舉
  • Redis Cluster:節點故障時的主從切換

2. 分布式鎖服務

  • Zookeeper:Leader選舉機制
  • etcd:Raft算法(更復雜的選舉算法)

3. 微服務架構

  • 服務注冊中心:主節點負責服務發現
  • 配置中心:主節點負責配置同步

與其他選舉算法對比

算法復雜度消息開銷收斂速度容錯性腦裂防護
Bully簡單中等中等需要額外機制
Ring中等天然防護
Raft復雜內置防護
Paxos復雜內置防護

總結

Bully算法是分布式系統中最重要的選舉算法之一。雖然存在腦裂、活鎖等問題,但通過合理的解決方案和最佳實踐,可以在大多數場景中提供可靠的選舉服務。

關鍵要點:

  1. 腦裂問題:通過多數派、租約、時間戳等機制解決
  2. 活鎖問題:使用隨機退避、優先級隊列、狀態機等避免
  3. 消息丟失:采用確認、重傳、批量等機制提高可靠性
  4. 性能優化:通過異步、緩存、批量等技術提升效率

在實際應用中,需要根據具體場景選擇合適的解決方案,并做好監控和告警。


Java實現示例

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;public class BullyNode {private final int nodeId;private final List<Integer> allNodes;private final AtomicInteger leaderId;private final AtomicBoolean isLeader;private final AtomicBoolean electionInProgress;private final ExecutorService executorService;private final Map<Integer, NodeStatus> nodeStatusCache;private final int quorumSize;private final int electionTimeout;public BullyNode(int nodeId, List<Integer> allNodes) {this.nodeId = nodeId;this.allNodes = new ArrayList<>(allNodes);this.leaderId = new AtomicInteger(-1);this.isLeader = new AtomicBoolean(false);this.electionInProgress = new AtomicBoolean(false);this.executorService = Executors.newCachedThreadPool();this.nodeStatusCache = new ConcurrentHashMap<>();this.quorumSize = allNodes.size() / 2 + 1;this.electionTimeout = 5000; // 5秒}public void startElection() {if (!electionInProgress.compareAndSet(false, true)) {return; // 選舉已在進行中}System.out.println("節點 " + nodeId + " 發起選舉");// 獲取更高優先級的節點List<Integer> higherNodes = allNodes.stream().filter(id -> id > nodeId).collect(Collectors.toList());if (higherNodes.isEmpty()) {// 沒有更高優先級的節點,直接成為主節點declareVictory();} else {// 向更高優先級的節點發送選舉消息CompletableFuture.runAsync(() -> {List<Integer> responses = sendElectionMessages(higherNodes);if (responses.isEmpty()) {declareVictory();} else {waitForVictory();}}, executorService);}}private List<Integer> sendElectionMessages(List<Integer> targetNodes) {List<Integer> responses = new ArrayList<>();for (Integer nodeId : targetNodes) {if (pingNode(nodeId)) {responses.add(nodeId);}}return responses;}private boolean pingNode(int targetNodeId) {// 模擬網絡延遲和節點故障try {Thread.sleep(new Random().nextInt(300) + 100);return new Random().nextDouble() > 0.2; // 80%概率節點存活} catch (InterruptedException e) {Thread.currentThread().interrupt();return false;}}private void declareVictory() {isLeader.set(true);leaderId.set(nodeId);electionInProgress.set(false);System.out.println("節點 " + nodeId + " 成為主節點");// 向所有節點發送Victory消息allNodes.stream().filter(id -> id != nodeId).forEach(this::sendVictoryMessage);}private void sendVictoryMessage(int targetNodeId) {System.out.println("節點 " + nodeId + " 向節點 " + targetNodeId + " 發送Victory消息");// 實際實現中這里會發送網絡消息}public void receiveVictory(int newLeaderId) {leaderId.set(newLeaderId);isLeader.set(newLeaderId == nodeId);electionInProgress.set(false);System.out.println("節點 " + nodeId + " 確認主節點為 " + newLeaderId);}private void waitForVictory() {System.out.println("節點 " + nodeId + " 等待Victory消息");// 設置超時機制CompletableFuture.delayedExecutor(electionTimeout, TimeUnit.MILLISECONDS).execute(() -> {if (electionInProgress.get()) {electionInProgress.set(false);startElection(); // 超時后重新發起選舉}});}// 腦裂防護:多數派機制public boolean declareVictoryWithQuorum() {List<Integer> responses = collectVictoryResponses();if (responses.size() >= quorumSize) {declareVictory();return true;}return false;}private List<Integer> collectVictoryResponses() {// 收集Victory響應return new ArrayList<>(); // 簡化實現}// 活鎖防護:隨機退避public void startElectionWithBackoff() {if (electionInProgress.compareAndSet(false, true)) {// 隨機延遲long delay = new Random().nextInt(2000);CompletableFuture.delayedExecutor(delay, TimeUnit.MILLISECONDS).execute(this::startElection);}}// 消息可靠性:重試機制public boolean sendWithRetry(int targetNode, String message, int maxRetries) {for (int attempt = 0; attempt < maxRetries; attempt++) {if (sendMessage(targetNode, message)) {return true;}try {Thread.sleep((long) Math.pow(2, attempt) * 1000); // 指數退避} catch (InterruptedException e) {Thread.currentThread().interrupt();break;}}return false;}private boolean sendMessage(int targetNode, String message) {// 模擬消息發送return new Random().nextDouble() > 0.1; // 90%成功率}// 監控指標private final AtomicInteger electionCount = new AtomicInteger(0);private final List<Long> electionDurations = new CopyOnWriteArrayList<>();public void recordElectionMetrics(long duration) {electionCount.incrementAndGet();electionDurations.add(duration);// 告警:選舉過于頻繁if (electionCount.get() > 10) {System.err.println("警告:選舉頻率過高");}}public void shutdown() {executorService.shutdown();try {if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) {executorService.shutdownNow();}} catch (InterruptedException e) {executorService.shutdownNow();Thread.currentThread().interrupt();}}// 使用示例public static void main(String[] args) {List<Integer> allNodes = Arrays.asList(1, 2, 3, 4, 5);Map<Integer, BullyNode> nodes = new HashMap<>();// 創建所有節點for (Integer nodeId : allNodes) {nodes.put(nodeId, new BullyNode(nodeId, allNodes));}// 模擬選舉過程System.out.println("=== Bully算法演示 ===");nodes.get(2).startElection();try {Thread.sleep(1000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}// 模擬節點4響應選舉System.out.println("\n=== 節點4響應選舉 ===");nodes.get(4).startElection();try {Thread.sleep(1000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}// 節點4成為主節點System.out.println("\n=== 節點4成為主節點 ===");nodes.get(4).declareVictory();// 其他節點接收Victory消息for (Integer nodeId : Arrays.asList(1, 2, 3, 5)) {nodes.get(nodeId).receiveVictory(4);}// 關閉所有節點nodes.values().forEach(BullyNode::shutdown);}
}

參考資料:

  • 分布式系統概念與設計
  • Zookeeper官方文檔
  • Redis Cluster文檔

相關文章:

  • 分布式系統中的一致性算法
  • Raft算法詳解
  • Paxos算法原理

ES的選舉算法

ES的選主算法是基于Bully算法的改進,主要思路是對節點ID排序,取ID值最大的節點作為Master,每個節點都運行這個流程。是不是非常簡單?選主的目的是確定唯一的主節點,初學者可能認為選舉出的主節點應該持有最新的元數據信息,實際上這個問題在實現上被分解為兩步:先確定唯一的、大家公認的主節點,再想辦法把最新的機器元數據復制到選舉出的主節點上。

基于節點ID排序的簡單選舉算法有三個附加約定條件:
(1)參選人數需要過半,達到 quorum(多數)后就選出了臨時的主。為什么是臨時的?每個節點運行排序取最大值的算法,結果不一定相同。舉個例子,集群有5臺主機,節點ID分別是1、2、3、4、5。當產生網絡分區或節點啟動速度差異較大時,節點1看到的節點列表是1、2、3、4,選出4;節點2看到的節點列表是2、3、4、5,選出5。結果就不一致了,由此產生下面的第二條限制。

(2)得票數需過半。某節點被選為主節點,必須判斷加入它的節點數過半,才確認Master身份。解決第一個問題。

(3)當探測到節點離開事件時,必須判斷當前節點數是否過半。如果達不到 quorum,則放棄Master身份,重新加入集群。如果不這么做,則設想以下情況:假設5臺機器組成的集群產生網絡分區,2臺一組,3臺一組,產生分區前,Master位于2臺中的一個,此時3臺一組的節點會重新并成功選取Master,產生雙主,俗稱腦裂。

集群并不知道自己共有多少個節點,quorum值從配置中讀取,我們需要設置配置項:
discovery.zen.minimum_master_nodes

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

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

相關文章

高效調試 AI 大模型 API:用 Apipost 實現 SSE 流式解析與可視化

借助 AI 大模型的實時接口&#xff08;如 OpenAI GPT 或其他第三方模型 API&#xff09;&#xff0c;開發者可以通過 SSE&#xff08;Server-Sent Events&#xff09;流式處理數據&#xff0c;實時獲取模型的逐步輸出。這一技術已廣泛應用于實時問答、代碼生成等領域。本文將基…

【網絡產品經營】園區網絡

園區網絡的產品經營邏輯發生顯著變化&#xff0c;從傳統的“連接功能”導向轉向“業務體驗驅動”&#xff0c;并結合行業場景化需求、技術架構革新及智能化能力提升&#xff0c;形成多維度的產品策略升級。 一、技術架構變革&#xff1a;從多層復雜到極簡全光 傳統架構的瓶頸與…

EasyExcel 4.X 讀寫數據

文章目錄 EasyExcel與SpringBoot集成讀數據讀取數據的流程定義實體類簡單讀取自定義監聽器 讀取指定sheet和所有sheet多行頭讀取數據格式轉換列表數據實體類自定義轉換器自定義監聽器數據讀取 寫數據簡單數據寫出存儲到磁盤返回前端下載 寫出指定列寬&#xff0c;和數值精度丟失…

JVM內存管理<一>:Java內存異常問題排查

一、 內存溢出問題的排查 1. 使用工具 - jdk自帶 jmapvisualvm 2. 流程 堆轉儲&#xff1a; (1) 方法一&#xff1a;程序運行時&#xff0c;采用&#xff1a;jmap -dump:formatb,filed:\\data\\xxlJob.hprof 23300 進行堆文件的轉儲 (2) 方法二&#xff1a;在內存溢出的時候…

Android中Glide.with().load().into() 應付面試源碼解析

1. with(this)&#xff1a;生命周期綁定 Glide.with(Activity/Fragment/Context) 核心機制&#xff1a;創建與 UI 生命周期綁定的 RequestManager 底層實現&#xff1a; 通過 RequestManagerRetriever 獲取單例 非 Application 上下文&#xff1a; 向 Activity/Fragment 添加…

#### es相關內容的索引 ####

倒排索引 結構 #### es倒排索引的結構 ####-CSDN博客 向量索引 結構應用 #### es向量檢索 的 結構及應用_es 向量 文本檢索-CSDN博客 ann算法 ann算法的種類有哪些&#xff0c;之間的區別&#xff0c;各自的適用場景-CSDN博客 地理信息索引 es地理信息索引的類型以及geo_po…

小飛電視:智能電視與移動設備的娛樂新選擇

在數字娛樂時代&#xff0c;人們對于影視內容的需求日益增長&#xff0c;不僅追求豐富多樣的節目選擇&#xff0c;還希望獲得便捷、個性化的觀看體驗。小飛電視正是這樣一款專為智能電視和移動設備設計的視頻娛樂應用&#xff0c;它憑借海量的影視資源、高清流暢的播放效果以及…

刪除node并且重裝然后重裝vue

參考第一篇文章 node.js卸載與安裝超詳細教程_node卸載重裝-CSDN博客 第二篇文章安裝vue Vue安裝與配置教程&#xff08;非常詳細&#xff09;_安裝vue-CSDN博客

基于YOLOv10算法的交通信號燈檢測與識別

目錄 一.&#x1f981; 寫在前面1.1 實現模塊劃分1.2 優化與實時性支持 二.&#x1f981; 相關技術與理論基礎2.1 各版本yolo對比2.2 YOLOv10網絡結構 三.&#x1f981; 結果分析3.1 訓練損失與驗證損失分析3.2 精確率&#xff08;Precision&#xff09;、召回率&#xff08;Re…

洪水風險圖制作全流程:HEC-RAS 與 ArcGIS 的耦合應用

技術點目錄 一、HER-RAS理論二、一維數學模型基本地形導入三、恒定流、非恒定流一維數學模型水流計算四、一維數學模型計算結果分析五、一維數學模型增設構筑物六、二維河道水動力模擬七、HEC-RAS在潰壩模型中的應用八、HEC-RAS在洪水風險圖中的應用了解更多 —————————…

視覺大語言模型未能充分利用視覺表征

視覺大語言模型未能充分利用視覺表征 FesianXu 20250612 at Wechat Search Team 前言 這兩天看到一篇新掛在arxiv上的文章 [1]&#xff0c;討論了下視覺大語言模型的視覺表征退化問題。先前的研究將VLM缺陷歸咎于視覺編碼器薄弱&#xff0c;并提出集成編碼器方案以彌補不足&am…

SSRF3 任意文件讀取

一.任意文件讀取 http://192.168.112.12/pikachu-master/vul/ssrf/ssrf_curl.php?urlfile:///etc/passwd 讀取文件使用 file://文件路徑即可&#xff0c;這里我們換協議為file&#xff0c;然后從根目錄開始讀取。 /etc/passwd 我們這樣修改完url路徑后查看結果可以看到文件內…

洛谷P3953 [NOIP 2017 提高組] 逛公園

洛谷P3953 [NOIP 2017 提高組] 逛公園 洛谷題目傳送門 題目背景 NOIP2017 D1T3 題目描述 策策同學特別喜歡逛公園。公園可以看成一張 N N N 個點 M M M 條邊構成的有向圖&#xff0c;且沒有 自環和重邊。其中 1 1 1 號點是公園的入口&#xff0c; N N N 號點是公園的出…

Vue3+TypeScript+Element Plus 表格展開行優化方案

在 Vue3 TypeScript Element Plus 項目中優化表格展開行的內存使用&#xff0c;主要從 渲染優化、數據管理 和 內存回收 三方面入手。以下是最佳實踐和完整解決方案&#xff1a; 1. 懶加載展開內容&#xff08;核心優化&#xff09; 只當行展開時才渲染內容&#xff0c;避免…

OpenCV——直方圖與匹配

直方圖與匹配 一、直方圖簡介二、直方圖統計三、直方圖比較四、直方圖均衡化五、自適應的直方圖均衡化六、直方圖反向投影七、模板匹配 一、直方圖簡介 圖像直方圖&#xff08;Histogram&#xff09;是一種頻率分布圖&#xff0c;它描述了不同強度值在圖像中出現的頻率。圖像直…

通義大模型在文檔自動化處理中的高效部署指南(OCR集成與批量處理優化)

1. 傳統OCR解決方案常面臨識別精度低、版面分析能力弱、處理效率瓶頸等問題。通義大模型憑借其多模態理解和生成能力&#xff0c;為文檔處理領域帶來革命性突破。本文將深入探討如何高效部署通義大模型實現端到端的文檔自動化處理&#xff0c;特別聚焦OCR集成與批量處理優化兩…

Ubuntu20.04通過ssh協議配置遠程終端

一、在目標計算機&#xff08;即被連接的計算機&#xff09;上操作&#xff1a; 1、安裝 OpenSSH 服務器&#xff1a; sudo apt update sudo apt install openssh-server3、啟動并設置 SSH 服務開機自啟&#xff1a; sudo systemctl enable --now ssh二、在源計算機&#xf…

《HTTP權威指南》 第7章 緩存

帶著問題學習&#xff1a; 緩存如何提高性能如何衡量緩存的有效性緩存置于何處作用最大HTTP如何保持緩存副本的新鮮度緩存如何與其他緩存及服務器通信 web緩存是可以自動保存常見文檔副本的HTTP設備。 緩存優點 減少冗余的數據傳輸&#xff0c;節省網絡費用緩解網絡瓶頸問題&…

第十三章 模板

函數模板 函數模板使用 函數模板注意事項 自動類型推導&#xff0c;必須推導出一致的數據類型T,才可以使用 模板必須要確定出T的數據類型&#xff0c;才可以使用 普通函數和函數模板的類型轉化 普通函數隱式類型轉化&#xff08;char轉int&#xff09; 函數模板正常使用不會發生…

云計算-專有網絡VPC

&#x1f310; 什么是 VPC&#xff1f;&#xff08;Virtual Private Cloud&#xff09; VPC&#xff08;Virtual Private Cloud&#xff0c;虛擬私有云&#xff09; 是公有云服務商提供的一種網絡隔離服務&#xff0c;允許用戶在云中創建一個邏輯隔離的私有網絡環境。你可以在這…