在现代的分布式系统和微服务架构中,数据同步和变更监控是保证系统一致性和实时性的核心问题之一。MySQL 数据库的 binlog(二进制日志)功能能够记录所有对数据库的修改操作,如插入(INSERT)、更新(UPDATE)、删除(DELETE)等,是实现实时数据变更同步的有效工具。
结合 Spring Boot 框架与腾讯云 MySQL 服务,通过 mysql-binlog-connector-java
库监听 MySQL 的 binlog 变化,可以实时捕捉数据库中的数据变更,并通过合适的前端展示技术(如 Bootstrap UI)动态呈现这些变化,增强系统的可视化和互动性。
本文将详细介绍如何在 Spring Boot 项目中实现 MySQL binlog 监听、数据变更处理,并通过 Bootstrap UI 动态展示变化效果,提供一个完整的解决方案。
本文将通过以下步骤展示如何实现数据变化监听和展示:
mysql-binlog-connector-java
来监听 MySQL binlog。在腾讯云上创建并配置 MySQL 数据库是实现数据监听的前提。首先登录腾讯云控制台并创建一个 MySQL 实例。在创建过程中,确保启用了 binlog(二进制日志)功能,并设置合适的日志格式(通常使用 ROW
格式以便捕获详细的行级变更信息)。
进入腾讯云控制台,选择 云数据库
,并创建一个新的 MySQL 实例。
在创建数据库实例时,在参数配置中启用 binlog,设置 binlog-format=row
。row
格式能够捕获更为详细的行级变更信息,适用于大多数变更监听场景。
[mysqld]
log-bin=mysql-bin
server-id=1
binlog-format=row
CREATE USER 'binlog_user'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'binlog_user'@'%';
FLUSH PRIVILEGES;
此用户将用于监听和读取 binlog 数据。
SHOW VARIABLES LIKE 'log_bin';
SHOW VARIABLES LIKE 'binlog_format';
如果返回值为 ON
和 ROW
,说明 binlog 配置已成功启用。
mysql-binlog-connector-java
首先创建一个 Spring Boot 项目,并在 pom.xml
中添加 mysql-binlog-connector-java
依赖:
<dependency>
<groupId>com.github.shyiko</groupId>
<artifactId>mysql-binlog-connector-java</artifactId>
<version>0.21.0</version>
</dependency>
这个依赖会帮助我们在 Spring Boot 项目中使用 mysql-binlog-connector-java
库来连接和监听 MySQL 的 binlog。
接下来,编写一个服务类,用于连接 MySQL 并监听 binlog 数据变化。在这个 BinlogService 类中,BinaryLogClient 被用来连接到 MySQL 服务器并监听 binlog 数据变化。监听到的事件会被添加到一个 LinkedBlockingQueue 中,这样我们可以在 Controller 中将这些数据展示到前端页面。通过 TableMapEventData 来获取表的映射关系。TableMapEventData 事件通常在 binlog 中包含了表名映射信息,它是与 WriteRowsEventData 一起生成的事件之一。WriteRowsEventData 实际上是通过 TableMapEventData 事件获得表 ID,然后使用这个 ID 来查找表名。
package com.example.demo.service;
import com.github.shyiko.mysql.binlog.BinaryLogClient;
import com.github.shyiko.mysql.binlog.event.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.*;
@Service
public class BinlogService {
@Value("${mysql.host}")
private String host;
@Value("${mysql.port}")
private int port;
@Value("${mysql.username}")
private String username;
@Value("${mysql.password}")
private String password;
private LinkedBlockingQueue<String> binlogChanges = new LinkedBlockingQueue<>();
// 存储 tableId -> tableName 的映射关系
private Map<Long, String> tableIdToNameMap = new HashMap<>();
// 开始监听 binlog
public void startListening() throws Exception {
BinaryLogClient client = new BinaryLogClient(host, port, username, password);
// 设置 serverId,防止与其他连接冲突
client.setServerId(12345);
// 注册 binlog 事件监听器
client.registerEventListener(new BinaryLogClient.EventListener() {
@Override
public void onEvent(Event event) {
EventHeaderV4 header = event.getHeader();
// 处理 TableMap 事件,用于记录表的映射关系
if (event.getData() instanceof TableMapEventData) {
TableMapEventData tableMapData = (TableMapEventData) event.getData();
tableIdToNameMap.put(tableMapData.getTableId(), tableMapData.getTable());
}
// 判断事件类型,处理不同的 binlog 事件
if (event.getData() instanceof WriteRowsEventData) {
WriteRowsEventData data = (WriteRowsEventData) event.getData();
String tableName = tableIdToNameMap.get(data.getTableId());
int rowsCount = data.getRows().size();
String message = String.format("INSERT事件:表 %s 插入了 %d 行数据", tableName, rowsCount);
binlogChanges.offer(message);
}
else if (event.getData() instanceof UpdateRowsEventData) {
UpdateRowsEventData data = (UpdateRowsEventData) event.getData();
String tableName = tableIdToNameMap.get(data.getTableId());
int rowsCount = data.getRows().size();
String message = String.format("UPDATE事件:表 %s 更新了 %d 行数据", tableName, rowsCount);
binlogChanges.offer(message);
}
else if (event.getData() instanceof DeleteRowsEventData) {
DeleteRowsEventData data = (DeleteRowsEventData) event.getData();
String tableName = tableIdToNameMap.get(data.getTableId());
int rowsCount = data.getRows().size();
String message = String.format("DELETE事件:表 %s 删除了 %d 行数据", tableName, rowsCount);
binlogChanges.offer(message);
}
}
});
// 连接并开始监听 binlog
client.connect();
}
// 获取最新的 binlog 数据变化
public LinkedBlockingQueue<String> getBinlogChanges() {
return binlogChanges;
}
}
在 application.properties
中配置 MySQL 的连接信息:
mysql.host=localhost
mysql.port=3306
mysql.username=binlog_user
mysql.password=password
在 Controller 中,我们将监听到的 binlog 变化通过模型传递给前端页面。在这个 Controller 中,index() 方法将 binlog 变化数据传递给前端页面。
package com.example.demo.controller;
import com.example.demo.service.BinlogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class BinlogController {
@Autowired
private BinlogService binlogService;
@GetMapping("/")
public String index(Model model) {
model.addAttribute("binlogChanges", binlogService.getBinlogChanges());
return "binlog";
}
}
如果在启动时需要监听 binlog 数据变化,需要确保在合适的时机启动监听器。例如,可以在 @PostConstruct
方法中启动,也可以使用 Spring Boot 的 CommandLineRunner
或 ApplicationRunner
来确保应用启动后执行相关任务。
package com.example.demo.config;
import com.example.demo.service.BinlogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class BinlogListenerRunner implements CommandLineRunner {
@Autowired
private BinlogService binlogService;
// @PostConstruct
// @Async // 异步执行 binlog 监听
// public void start() {
// }
@Override
public void run(String... args) throws Exception {
try {
binlogService.startListening();
} catch (Exception e) {
e.printStackTrace();
}
}
}
我们使用 Thymeleaf 模板引擎来动态渲染页面。首先,在 src/main/resources/templates
目录下创建一个 index.html
文件,并引入 Bootstrap UI 和 Thymeleaf 标签。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Binlog 数据变化展示</title>
<!-- 引入 Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<div class="container">
<h1 class="text-center my-4">Binlog 数据变化监控</h1>
<!-- 动态展示数据变化 -->
<div id="binlogChanges" class="row">
<div class="col-md-4" th:each="change : ${binlogChanges}">
<div class="card mb-3">
<div class="card-body">
<h5 class="card-title">数据变化</h5>
<p class="card-text" th:text="${change}"></p>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#changeDetailsModal"
th:attr="data-bs-whatever=${change}">查看详情</button>
</div>
</div>
</div>
</div>
<!-- 模态框展示详细信息 -->
<div class="modal fade" id="changeDetailsModal" tabindex="-1" aria-labelledby="changeDetailsModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="changeDetailsModalLabel">数据变化详情</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p id="changeDetails">详细信息加载中...</p>
</div>
</div>
</div>
</div>
</div>
<script>
var changeDetailsModal = document.getElementById('changeDetailsModal');
changeDetailsModal.addEventListener('show.bs.modal', function (event) {
var button = event.relatedTarget;
var changeDetails = button.getAttribute('data-bs-whatever');
var modalBody = changeDetailsModal.querySelector('.modal-body #changeDetails');
modalBody.textContent = changeDetails;
});
</script>
</body>
</html>
在页面加载时,通过 th:each
将后台的 binlog 变化数据动态展示在卡片中。每当新的数据变化被监听到,前端页面会自动更新并显示最新的变化。
通过以上方法,您可以创建一个高效、可靠的实时数据监听与展示系统。
通过结合 Spring Boot 框架和腾讯云 MySQL 服务,利用 binlog 监听 MySQL 数据变化并在前端展示,我们能够实时捕捉并展示数据库的变化,极大地提升了系统的响应性和实时性。在前端,我们使用了 Bootstrap UI 组件,如卡片、按钮和模态框,创建了一个用户友好的界面。
通过将数据存储和处理卸载到腾讯云MySQL,CVM可以专注于处理应用逻辑和业务需求,减轻数据库管理、查询优化、存储管理等方面的负担。腾讯云MySQL提供的高性能、自动化运维、分布式架构、数据安全等功能,有助于提升系统的稳定性、可扩展性和性能,进而减少CVM服务器的功能压力,使得整体系统更加高效、可靠。
腾讯云MySQL是一个完全托管的数据库服务,用户无需担心数据库的硬件资源、备份、维护和高可用性配置等问题。通过使用腾讯云MySQL,CVM可以将业务逻辑的复杂性转移到数据库层,减轻服务器的处理负担。
腾讯云MySQL拥有丰富的查询优化工具和调优功能(如查询缓存、索引优化、SQL调优等),通过合理的设计和配置,可以显著提高数据库的查询性能,减轻CVM服务器的负担。
腾讯云MySQL支持分布式数据库架构(如读写分离、分表分库、Sharding等)。通过合理配置,可以将数据库负载分散到多个节点上,避免单一CVM服务器的过载。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。