SpringBoot與BookKeeper整合,實現金融級別的日志存儲系統

BookKeeper的優勢

高吞吐量和低延遲

  • 分布式架構: Apache BookKeeper采用分布式的架構設計,能夠支持高并發的寫入和讀取操作。

  • 批量寫入: 支持批量寫入日志條目,顯著提高寫入效率。

  • 異步I/O: 使用異步I/O操作,減少等待時間,提升整體性能。

數據一致性和持久性

  • 強一致性保證: BookKeeper提供強一致性保證,確保所有寫入的數據都能被正確讀取。

  • 多副本復制: 數據在多個Bookies(BookKeeper節點)上進行多副本復制,防止單點故障導致的數據丟失。

  • 自動恢復: 在節點故障時,BookKeeper能夠自動檢測并恢復數據,確保系統的連續運行。

水平擴展能力

  • 動態擴展: 可以通過增加Bookies來擴展集群規模,適應不斷增長的業務需求。

  • 負載均衡: 自動分配負載,確保各節點之間的工作負載平衡,避免熱點問題。

  • 靈活性: 支持多種部署方式,包括本地部署、云部署等。

數據加密和訪問控制

  • 數據加密: 支持對存儲的日志數據進行加密處理,防止未授權訪問。

  • 認證和授權: 提供細粒度的權限管理機制,限制不同角色的訪問權限。

  • 審計日志: 記錄所有對系統的訪問和操作,便于追蹤和審計。

記得啟動ZooKeeper服務器

因為BookKeeper依賴于ZooKeeper來進行元數據管理和協調!!!

代碼實操

<project?xmlns="http://maven.apache.org/POM/4.0.0"?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.5</version><relativePath/><!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>bookkeeper-springboot-example</artifactId><version>0.0.1-SNAPSHOT</version><name>bookkeeper-springboot-example</name><description>Demo project for Spring Boot and Apache BookKeeper integration</description><properties><java.version>11</java.version></properties><dependencies><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Apache BookKeeper Client --><dependency><groupId>org.apache.bookkeeper</groupId><artifactId>bookkeeper-server</artifactId><version>4.18.0</version></dependency><!-- Jackson Databind for JSON processing --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency><!-- Lombok for reducing boilerplate code --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- Test dependencies --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

application.properties

# ZooKeeper 連接字符串
bookkeeper.zk.connectString=localhost:2181
server.port=8080

配置類

package?com.example.bookkeeperspringbootexample.config;import?org.apache.bookkeeper.client.BookKeeper;
import?org.apache.bookkeeper.client.LedgerHandle;
import?org.apache.bookkeeper.conf.ClientConfiguration;
import?org.slf4j.Logger;
import?org.slf4j.LoggerFactory;
import?org.springframework.beans.factory.annotation.Value;
import?org.springframework.context.annotation.Bean;
import?org.springframework.context.annotation.Configuration;import?javax.annotation.PreDestroy;
import?java.io.IOException;@Configuration
publicclass?BookKeeperConfig?{privatestaticfinal?Logger logger = LoggerFactory.getLogger(BookKeeperConfig.class);@Value("${bookkeeper.zk.connectString}")private?String zkConnectString;private?BookKeeper bookKeeper;private?LedgerHandle ledgerHandle;/*** 初始化BookKeeper客戶端**?@return?BookKeeper實例*?@throws?IOException 如果初始化失敗*/@Beanpublic?BookKeeper?bookKeeper()?throws?IOException?{ClientConfiguration conf =?new?ClientConfiguration();conf.setZkServers(zkConnectString);bookKeeper =?new?BookKeeper(conf);logger.info("BookKeeper客戶端已初始化。");return?bookKeeper;}/*** 創建一個新的Ledger**?@param?bookKeeper BookKeeper實例*?@return?LedgerHandle實例*?@throws?Exception 如果創建Ledger失敗*/@Beanpublic?LedgerHandle?ledgerHandle(BookKeeper bookKeeper)?throws?Exception?{ledgerHandle = bookKeeper.createLedger(BookKeeper.DigestType.CRC32,"password".getBytes());logger.info("Ledger已創建,ID: {}", ledgerHandle.getId());return?ledgerHandle;}/*** 關閉BookKeeper客戶端和Ledger*/@PreDestroypublic?void?shutdown()?throws?InterruptedException, BookKeeper.BKException?{if?(ledgerHandle !=?null) {ledgerHandle.close();logger.info("Ledger已關閉。");}if?(bookKeeper !=?null) {bookKeeper.close();logger.info("BookKeeper客戶端已關閉。");}}}

交易的數據模型

package?com.example.bookkeeperspringbootexample.model;import?lombok.Data;import?java.time.LocalDateTime;/*** 表示交易的數據模型*/
@Data
public?class?Transaction?{private?Long transactionId;?// 交易IDprivate?Double amount; ? ? ?// 交易金額private?LocalDateTime timestamp;?// 時間戳
}

服務類

package?com.example.bookkeeperspringbootexample.service;import?com.example.bookkeeperspringbootexample.model.Transaction;
import?com.fasterxml.jackson.databind.ObjectMapper;
import?org.apache.bookkeeper.client.BKException;
import?org.apache.bookkeeper.client.LedgerHandle;
import?org.apache.bookkeeper.proto.BookieProtocol;
import?org.slf4j.Logger;
import?org.slf4j.LoggerFactory;
import?org.springframework.beans.factory.annotation.Autowired;
import?org.springframework.stereotype.Service;import?java.io.IOException;
import?java.util.concurrent.CompletableFuture;
import?java.util.concurrent.ExecutionException;@Service
publicclass?BookKeeperService?{privatestaticfinal?Logger logger = LoggerFactory.getLogger(BookKeeperService.class);@Autowiredprivate?LedgerHandle ledgerHandle;@Autowiredprivate?ObjectMapper objectMapper;/*** 異步添加交易到BookKeeper**?@param?transaction 交易對象*?@return?CompletableFuture<Long> 包含新條目的entryId*/public?CompletableFuture<Long>?addTransaction(Transaction transaction)?{try?{byte[] logData = objectMapper.writeValueAsBytes(transaction);?// 將交易對象轉換為字節數組return?CompletableFuture.supplyAsync(() -> {try?{long?entryId = ledgerHandle.addEntry(logData);?// 將字節數組添加到Ledgerlogger.info("已添加交易,entryId: {}", entryId);return?entryId;}?catch?(BKException | InterruptedException e) {thrownew?RuntimeException(e);}});}?catch?(IOException e) {thrownew?RuntimeException(e);}}/*** 異步從BookKeeper讀取交易**?@param?entryId 條目ID*?@return?CompletableFuture<Transaction> 包含讀取的交易對象*/public?CompletableFuture<Transaction>?readTransaction(long?entryId)?{return?CompletableFuture.supplyAsync(() -> {try?{LedgerSequence seq = ledgerHandle.readEntries(entryId, entryId);?// 讀取指定entryId的條目if?(seq.hasMoreElements()) {LedgerEntry entry = seq.nextElement();?// 獲取條目byte[] data = entry.getEntryBytes();?// 獲取條目的字節數組logger.info("已讀取交易,entryId: {}", entryId);return?objectMapper.readValue(data, Transaction.class);?// 將字節數組轉換為交易對象}thrownew?IllegalArgumentException("未找到ID為 "?+ entryId +?" 的交易");}?catch?(BKException | InterruptedException | ExecutionException | IOException e) {thrownew?RuntimeException(e);}});}}

Controller

package?com.example.bookkeeperspringbootexample.controller;import?com.example.bookkeeperspringbootexample.model.Transaction;
import?com.example.bookkeeperspringbootexample.service.BookKeeperService;
import?org.springframework.beans.factory.annotation.Autowired;
import?org.springframework.http.ResponseEntity;
import?org.springframework.web.bind.annotation.*;import?java.util.concurrent.CompletableFuture;@RestController
@RequestMapping("/transactions")
publicclass?TransactionController?{@Autowiredprivate?BookKeeperService bookKeeperService;/*** 添加新的交易**?@param?transaction 交易對象*?@return?ResponseEntity<Long> 包含新條目的entryId*/@PostMapping("/")public?ResponseEntity<Long>?addTransaction(@RequestBody Transaction transaction)?{CompletableFuture<Long> futureEntryId = bookKeeperService.addTransaction(transaction);?// 異步添加交易try?{Long entryId = futureEntryId.get();?// 獲取結果return?ResponseEntity.ok(entryId);?// 返回成功的HTTP響應}?catch?(InterruptedException | ExecutionException e) {Thread.currentThread().interrupt();?// 中斷線程return?ResponseEntity.internalServerError().build();?// 返回內部服務器錯誤}}/*** 根據entryId讀取交易**?@param?entryId 條目ID*?@return?ResponseEntity<Transaction> 包含讀取的交易對象*/@GetMapping("/{entryId}")public?ResponseEntity<Transaction>?getTransaction(@PathVariable?long?entryId)?{CompletableFuture<Transaction> futureTransaction = bookKeeperService.readTransaction(entryId);?// 異步讀取交易try?{Transaction transaction = futureTransaction.get();?// 獲取結果return?ResponseEntity.ok(transaction);?// 返回成功的HTTP響應}?catch?(InterruptedException | ExecutionException e) {Thread.currentThread().interrupt();?// 中斷線程return?ResponseEntity.notFound().build();?// 返回未找到資源}}}

Application

package?com.example.bookkeeperspringbootexample;import?org.springframework.boot.SpringApplication;
import?org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public?class?BookKeeperSpringBootExampleApplication?{public?static?void?main(String[] args)?{SpringApplication.run(BookKeeperSpringBootExampleApplication.class,?args);}}

測試

添加交易

curl -X POST http://localhost:8080/transactions/ \
-H?"Content-Type: application/json"?\
-d?'{"transactionId": 1, "amount": 100.50, "timestamp": "2025-03-19T21:36:06"}'

Respons:

1

讀取交易

curl -X GET http://localhost:8080/transactions/1

Respons:

{"transactionId":1,"amount":100.5,"timestamp":"2025-03-19T21:36:06"}

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

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

相關文章

【Bug】 [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed

當你在進行深度學習相關操作時&#xff0c;若因缺少本地的 CA 證書而無法下載資源&#xff0c;下面為你介紹幾種解決辦法&#xff1a; 方法一&#xff1a;更新 CA 證書 在大多數 Linux 發行版中&#xff0c;你可以使用包管理器來更新 CA 證書。例如&#xff0c;在基于 Debian…

Vue3中AbortController取消請求的用法詳解

在 Vue3 中&#xff0c;AbortController 用于取消 fetch 請求&#xff0c;避免組件卸載后仍執行異步操作導致的潛在問題&#xff08;如內存泄漏或更新已銷毀組件的狀態&#xff09;。以下是詳細用法和最佳實踐&#xff1a; 一、基本用法 創建 AbortController 實例 在組件 setu…

【刷題Day26】Linux命令、分段分頁和中斷(淺)

說下你常用的 Linux 命令&#xff1f; 文件與目錄操作&#xff1a; ls&#xff1a;列出當前目錄的文件和子目錄&#xff0c;常用參數如-l&#xff08;詳細信息&#xff09;、-a&#xff08;包括隱藏文件&#xff09;cd&#xff1a;切換目錄&#xff0c;用于在文件系統中導航m…

Spring Boot 參考文檔導航手冊

&#x1f4da; Spring Boot 參考文檔導航手冊 &#x1f5fa;? ? 新手入門 &#x1f476; 1?? &#x1f4d6; 基礎入門&#xff1a;概述文檔 | 環境要求 | 安裝指南 2?? &#x1f527; 實操教程&#xff1a;上篇 | 下篇 3?? &#x1f680; 示例運行&#xff1a;基礎篇 …

卷積神經網絡(CNN)詳細教程

卷積神經網絡&#xff08;CNN&#xff09;詳細教程 一、引言 卷積神經網絡&#xff08;Convolutional Neural Networks, CNN&#xff09;是一種深度學習模型&#xff0c;廣泛應用于圖像識別、視頻分析、自然語言處理等領域。CNN通過模擬人類視覺系統的層次結構&#xff0c;能夠…

解決SSLError: [SSL: DECRYPTION_FAILED_OR_BAD_RECORD_MAC] decryption faile的問題

問題描述&#xff1a; 在pip安裝第三方庫時&#xff0c;出現SSL的問題。 傳輸層安全性協議&#xff08;TLS&#xff09;及其前身安全套接層&#xff08;SSL&#xff09;是現在的 HTTPS 協議中的一種安全協議&#xff0c;目的是為互聯網通信提供安全及數據完整性保障。而較新版…

SpringBoot程序的創建以及特點,配置文件,LogBack記錄日志,配置過濾器、攔截器、全局異常

目錄 一、創建一個SpringBoot程序 二、SpringBoot的特點 ①主要特點 ②其他特點 ③熱部署 啟動熱部署 關閉熱部署 三、SpringBoot的配置文件 ①SpringBoot三種配置文件的格式&#xff08;以設置端口號為例&#xff09;&#xff1a; ②配置文件的優先級 ③常見配置項 1…

i18n-ai-translate開源程序,可以使用DeepSeek等模型將您的 i18nJSON翻譯成任何語言

一、軟件介紹 文末提供程序和源碼下載 i18n-ai-translate開源程序使用 DeepSeek等模型可以將您的 i18n JSON 翻譯成任何語言。 無縫翻譯本地化文件。支持嵌套翻譯文件的目錄。需要i18next樣式的JSON 文件&#xff08;文末一并提供下載&#xff09;。 二、模式 CSV 模式 三個…

Flask + ajax上傳文件(一)--單文件上傳

一、概述 本教程將教你如何使用Flask后端和AJAX前端實現文件上傳功能,包含完整的代碼實現和詳細解釋。 二、環境準備 1. 所需工具和庫 Python 3.xFlask框架jQuery庫Bootstrap(可選,用于美化界面)2. 安裝Flask pip install flask三、項目結構 upload_project/ ├── a…

如何在 Postman 中,自動獲取 Token 并將其賦值到環境變量

在 Postman 中&#xff0c;你可以通過 預請求腳本&#xff08;Pre-request Script&#xff09; 和 測試腳本&#xff08;Tests&#xff09; 實現自動獲取 Token 并將其賦值到環境變量&#xff0c;下面是完整的操作步驟&#xff1a; ? 一、創建獲取 Token 的請求 通常這個請求…

北斗導航 | 基于Transformer+LSTM+激光雷達的接收機自主完好性監測算法研究

基于Transformer+LSTM+激光雷達的接收機自主完好性監測算法研究 接收機自主完好性監測(RAIM)是保障全球導航衛星系統(GNSS)定位可靠性的核心技術。傳統RAIM算法依賴最小二乘殘差法,存在故障漏檢、對復雜環境適應性差等問題。結合Transformer、LSTM與激光雷達的多模態融合…

基于Python爬蟲的豆瓣電影信息爬取(可以根據選擇電影編號得到需要的電影信息)

# 豆瓣電影信息爬蟲(展示效果如下圖所示:) 這是一個功能強大的豆瓣電影信息爬蟲程序,可以獲取豆瓣電影 Top 250 的詳細信息。 ## 功能特點 - 自動爬取豆瓣電影 Top 250 的所有電影信息 - 支持分頁獲取,每頁 25 部電影,共 10 頁 - 獲取每部電影的詳細信息,包括: - 標題…

Ubuntu22.04/24.04 P104-100 安裝驅動和 CUDA Toolkit

硬件環境 使用一塊技嘉 B85m-DS3H 安裝 P104-100, CPU是帶集成顯卡的i5-4690. 先在BIOS中設置好顯示設備優先使用集成顯卡(IGX). 然后安裝P104-100開機. 登入Ubuntu 后查看硬件信息, 檢查P104-100是否已經被檢測到 # PCI設備 lspci -v | grep -i nvidia lspci | grep NVIDIA …

東南亞與中東小游戲市場出海調研報告

東南亞與中東小游戲市場出海調研報告 目標市場篩選與概況 (The Gaming Market in Southeast Asia (SEA) | Allcorrect)圖:2018–2027年東南亞主要國家游戲市場收入(億美元)趨勢。到2024年東南亞游戲市場規模預計將接近300億美元 (2024年東南亞手游市場怎么樣? - 快出海問…

力扣4-最長公共前綴

一.題目 編寫一個函數來查找字符串數組中的最長公共前綴。 如果不存在公共前綴&#xff0c;返回空字符串 ""。 示例 1&#xff1a; 輸入&#xff1a;strs ["flower","flow","flight"] 輸出&#xff1a;"fl"示例 2&…

設計模式和單一原則筆記

單一原則&#xff1a;方法 對象 策略模式&#xff1a;方法實現 // 策略接口&#xff08;單一職責&#xff1a;定義計算規范&#xff09; public interface PriceStrategy {boolean match(String type); // 職責1&#xff1a;判斷是否適用該策略double calculate(double pric…

常見正則表達式整理與Java使用正則表達式的例子

一、常見正則表達式整理 1. 基礎驗證類 郵箱地址 ^[a-zA-Z0-9._%-][a-zA-Z0-9.-]\\.[a-zA-Z]{2,}$ &#xff08;匹配如 userexample.com&#xff09;手機號 ^1[3-9]\\\\d{9}$ &#xff08;匹配國內11位手機號&#xff0c;如 13812345678&#xff09;中文字符 ^[\u4e00-\u9fa5…

vue2 項目的 vscode 插件整理

Folder Selector 當項目文件很多時&#xff0c;查找一個文件&#xff0c;可能需要在資源管理器中不斷的滾動再打開文件夾查找文件&#xff0c;很麻煩&#xff0c;這個可以增加一個面板通過右鍵文件夾選擇 然后在面板中查看文件 Reveal Button 文件中跳轉到另一個文件時&#…

使用 Node、Express 和 MongoDB 構建一個項目工程

本文將詳細介紹如何使用 Node.js Express MongoDB 構建一個完整的 RESTful API 后端項目&#xff0c;涵蓋&#xff1a; 項目初始化 Express 服務器搭建 MongoDB 數據庫連接 REST API 設計&#xff08;CRUD 操作&#xff09; 錯誤處理與中間件 源碼結構與完整代碼 部署建…

如何實現Spring Boot應用程序的安全性:全面指南

在現代 Web 開發中&#xff0c;安全性是 Spring Boot 應用程序的核心需求&#xff0c;尤其是在微服務、云原生和公開 API 場景中。Spring Boot 結合 Spring Security 提供了一套強大的工具&#xff0c;用于保護應用程序免受常見威脅&#xff0c;如未經授權的訪問、數據泄露、跨…