高可用性技术与容错数据收集器的实现
立即解锁
发布时间: 2025-08-29 10:53:36 阅读量: 8 订阅数: 18 AIGC 

### 高可用性技术与容错数据收集器的实现
#### 1. 主从代码运行与测试
在运行代码时,不要被其复杂性吓倒。尽管代码使用了条件编译,增加了一定的复杂度,但它避免了创建两个项目的麻烦。主从设备需要相同的代码与 MySQL 服务器和传感器进行通信,这样编写一次代码可以节省调试和维护重复代码的精力。
在自行运行代码之前,先仔细阅读代码。同时,在运行代码前,务必再三检查接线,这一步可能比较棘手。
##### 1.1 测试步骤
测试代码的过程如下:
1. **编译并上传到主设备**:注释掉 `#define`,选择正确的开发板和端口,然后上传代码。
2. **编译并上传到从设备**:取消 `#define` 的注释,选择从设备对应的正确开发板和端口,再进行编译和上传。
建议将主从设备都通过 USB 连接到计算机,这样可以更方便地进行实验设置。只需在 Arduino IDE 中设置端口并启动串口监视器,就可以在主从设备之间切换。不过要注意,当串口监视器连接时,Arduino 会被强制复位,这在测试时是正常的,但可能需要等待几秒钟才能看到主从代码开始工作。
##### 1.2 测试输出检查
- **连接主设备**:通过串口监视器连接主设备时,会看到类似图 8 - 5 的输出。这有助于判断主设备是否正在发送消息。同时,注意连接的 LED,它应该会随着每条消息反馈而闪烁。
- **连接从设备**:连接从设备时,会看到显示从设备是否收到消息(心跳信号)以及经过时间的计数器的消息。如果主设备出现故障,也会有相应的提示消息,如图 8 - 6 所示。
如果遇到问题,不要灰心。返回检查接线,确保一切连接正确。确认接线无误后,再次编译并上传代码,确保为每个主从设备使用了正确的开发板和端口。有时可能会不小心将从设备(或主设备)的代码上传到两个板子上,如果遇到这种情况,也可以使用两个单独的代码文件。
此外,考虑先上传主设备代码并让其运行,再上传从设备代码,然后连接到从设备的串口监视器输出,这样有时可以让操作更清晰。最后,要确保主从设备之间没有电源问题或电源不兼容的情况。
当看到正确的输出时,就说明代码运行成功了。这个看似简单的代码实现了复杂的心跳机制和自动故障转移功能,这是一些更强大硬件的解决方案可能无法实现的。
#### 2. 实际测试与后续操作
将主从设备从笔记本电脑上拔下并通电,建议先开启主设备,再开启从设备。观察主设备上的 LED 是否先闪烁,然后从设备上的 LED 是否也闪烁。只要这些 LED 闪烁,就说明主设备的心跳信号正在发送和接收。如果没有看到这种情况,可以尝试重置或关闭设备,然后再重新开启,有时 I2C 总线可能启动不正常,重启似乎会有所帮助。
当确认一切正常后,就可以添加读取传感器数据并将数据写入 MySQL 数据库的代码,然后在物联网解决方案中部署具有故障转移功能的冗余数据收集器。要注意,较小的开发板可能没有足够的内存来支持多个大型库,因此可能需要使用更大的 Arduino 开发板。同时,要找到 SDA 和 SCL 引脚并正确接线。
#### 3. 容错数据收集器项目
实现 MySQL 的容错并不太难,可以通过 MySQL 复制来实现冗余、恢复、可扩展性和最终的高可用性。但在基于微控制器的节点上实现写入数据库时的容错则更具挑战性。
##### 3.1 项目概述
本项目是一个简单的植物土壤湿度数据收集器,具备故障检测和恢复功能,用于将数据写入数据库。数据收集器的基本功能是从一个或多个传感器读取数据,然后将数据传递给数据节点、数据库,或者将数据本地存储到文件中。本项目主要关注数据收集器与数据库服务器连接的故障,即节点在网络中孤立、数据库服务器故障或其他通信中断的情况。
##### 3.2 设计目标
目标是使节点对数据库连接具有容错能力。具体来说,当数据库无法访问时,将数据本地存储(缓存)到 SD 卡中,当数据库恢复可访问时,将缓存的数据保存到数据库中。
数据库是一个简单的结构,包含一个表,用于记录土壤湿度传感器的值以及读取(存储)该值的日期和时间。创建示例数据库的 SQL 语句如下:
```sql
CREATE DATABASE `plant_moisture`;
CREATE TABLE `plant_moisture`.`plants` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`moisture_raw` int(11) DEFAULT NULL,
`date_saved` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=257 DEFAULT CHARSET=latin1;
```
##### 3.3 硬件组装
项目所需的硬件包括 Arduino、土壤湿度传感器、以太网屏蔽罩和实时时钟模块。
使用 Arduino Mega 的原因是故障检测和恢复功能对资源要求较高。Arduino Uno 等小型开发板内存有限,而本项目需要添加大量库,如用于连接 MySQL 服务器的 Connector/Arduino、用于缓存数据的 SD 卡库以及用于读取日期和时间的 RTC 模块库,再加上检测故障和恢复的代码,很容易超出 Uno 板的内存限制,因此选择具有足够内存的 Mega 板。
RTC 模块的作用是获取当前日期和时间,因为数据库中有一个时间戳列用于存储样本的存储时间。如果检测到故障,在一段时间后重新连接到数据库服务器时,数据库服务器会使用写入数据库的日期和时间,而不是样本采集的时间,所以需要 RTC 模块来确保缓存数据中包含正确的日期和时间。
接线连接如下:
- **土壤湿度传感器**:5V 和地连接到 Arduino,传感器的信号线连接到 Arduino 的模拟引脚 0。
- **RTC 模块**:SDA 和 SCL 引脚分别连接到 Arduino Mega 的 20 号和 21 号引脚,同时从 Arduino 获取 5V 和地。
#### 4. 代码实现
在编写代码之前,先明确设计目标和关键要求:
- 所有收集的数据都应保存到数据库中。
- 测试数据库连接,确保服务器已连接。
- 当数据库无法连接时,将数据存储到本地文件。
- 本地文件中的数据应写入板载 SD 卡。
- 当数据库连接恢复且本地文件中有数据时,读取数据并插入到数据库中。
- 缓存的数据应存储样本采集的正确日期和时间。
##### 4.1 高级算法
以下是 `loop()` 方法的高级概述,它是驱动代码的“主”程序:
```plaintext
read_sample()
if <database connection fails> then
cache_data() // save data to the file
else
dump_cache() // read data from file and insert into database
write_data() // save current sample
end if
```
从这个算法可以看出,需要三个主要方法以及检测数据库连接是否失败的方法。
##### 4.2 各部分代码实现
- **读取样本**:由于使用的是模拟传感器,可以使用 `analogRead()` 方法读取传感器数据:
```cpp
value = analogRead(sensorPin);
```
- **检测数据库连接失败**:一种更好的方法是在每次循环中尝试 `connect()`,并在保存数据后调用 `close()`。`connect()` 方法在服务器不可达时会更快返回。示例代码如下:
```cpp
// Attempt to connect to the database server
if (!conn.connected()) {
if (conn.connect(server_addr, 3306, user, password)) {
...
}
}
...
conn.close();
```
- **将数据写入文件**:需要使用 SD 库,打开文件、写入数据并关闭文件。关键是要获取日期和时间字符串并写入文件,以保留样本采集的时间。
- **将数据写入数据库**:代码如下:
```cpp
bool write_data(int val, const char *dateStr) {
String queryStr = String("INSERT INTO plant_moisture.plants VALUES (NULL,");
queryStr += String(val);
que
```
0
0
复制全文
相关推荐










