概述
对数据库表数据进行监听,保证表的数据量不大的情况下,当有数据新增时,需要对数据进行处理或者触发其他业务操作。
1、配置RocketMQ、Redis、Mybatis-plus依赖
在pom.xml文件中添加所需的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>版本号</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>版本号</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
2、配置RocketMQ、MySQL、Redis连接信息
在application.properties文件中配置RocketMQ和MySQL的连接信息:
# RocketMQ配置
rocketmq.name-server=127.0.0.1:9876
# MySQL配置
spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase
spring.datasource.username=root
spring.datasource.password=password
# Redis配置
spring.redis.host=localhost
spring.redis.port=6379
3、创建实体类和Mapper
// User.java
@Data
public class User {
private Long id;
private String name;
// 其他字段...
}
// UserMapper.java
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
4、创建RocketMQ消息生产者
@Service
public class MessageProducer {
@Autowired
private RocketMQTemplate rocketMQTemplate;
public void sendMessage(String topic, User user) {
rocketMQTemplate.convertAndSend(topic, user);
}
}
5、创建触发器
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
@Component
public class TableChangeTrigger {
@Autowired
private MessageProducer messageProducer;
@Autowired
private UserMapper userMapper;
@Autowired
private RedisTemplate<String, Long> redisTemplate;
@Scheduled(cron = "0/5 * * * * ?") // 每5秒执行一次
public void checkTableChange() {
List<User> userList = userMapper.selectList(null);
// 检查是否有新增数据
Long lastMaxId = getLastMaxId(); // 获取上一次查询的最大id
Long currentMaxId = getMaxId(userList); // 获取当前查询的最大id
if (lastMaxId < currentMaxId) {
List<User> newUsers = getNewUsers(userList, lastMaxId, currentMaxId); // 获取新增数据
processNewUsers(newUsers); // 发送新增数据到MQ
updateLastMaxId(currentMaxId); // 更新最大id
}
}
//获取上次最大id值
private Long getLastMaxId() {
ValueOperations<String, Long> valueOperations = redisTemplate.opsForValue();
return valueOperations.get("lastMaxId");
}
//获取当前查询的最大id
private Long getMaxId(List<User> userList) {
if (userList.isEmpty()) {
return 0L;
}
return userList.get(userList.size() - 1).getId();
}
//获取距上次执行新增的数据
private List<User> getNewUsers(List<User> userList, Long lastMaxId, Long currentMaxId) {
List<User> newUsers = new ArrayList<>();
for (User user : userList) {
if (user.getId() > lastMaxId && user.getId() <= currentMaxId) {
newUsers.add(user);
}
}
return newUsers;
}
//将新增的数据发送到MQ
private void processNewUsers(List<User> newUsers) {
for (User user : newUsers) {
messageProducer.sendMessage("myTopic", user);
}
}
//将现在的最大id值更新到Redis中
private void updateLastMaxId(Long currentMaxId) {
ValueOperations<String, Long> valueOperations = redisTemplate.opsForValue();
valueOperations.set("lastMaxId", currentMaxId);
}
}
6、创建RocketMQ消息消费者类
@Service
@RocketMQMessageListener(topic = "myTopic", selectorExpression = "*", consumerGroup = "myConsumerGroup")
public class MessageConsumer implements RocketMQListener<User>, RocketMQPushConsumerLifecycleListener {
private static final int MAX_RETRY_TIMES = 3; // 最大重试次数
private static final long RETRY_INTERVAL = 3000; // 重试间隔时间(毫秒)
@Override
public void onMessage(User user) {
int retryTimes = 0;
while (retryTimes < MAX_RETRY_TIMES) {
try {
// 处理接收到的User对象
System.out.println("Received user: " + user);
// 执行相应的操作
break; // 消费成功,跳出循环
} catch (Exception e) {
retryTimes++;
if (retryTimes < MAX_RETRY_TIMES) {
try {
Thread.sleep(RETRY_INTERVAL);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
} else {
// 超过最大重试次数,记录日志或进行其他处理
System.out.println("Failed to process message: " + user);
}
}
}
}
@Override
public void prepareStart(DefaultMQPushConsumer consumer) {
consumer.setConsumeMessageBatchMaxSize(1);
consumer.setConsumeThreadMin(1);
consumer.setConsumeThreadMax(1);
}
}
总结
通过采用定时任务的方式,定时查询数据库表新增的数据从而实现对表数据新增的监听。若表数据量大则需要采用多线程定时任务的方式进行优化。