数据同步
es的数据的源数据一般会存储再mysql数据库里面 或者数据仓库中,因此源数据发生变化时,es也必须跟着改变。
在分布式系统中,源数据管理 和ES搜索服务 一般时完全隔离的,不会将他们耦合在一起, 比如我们有一个数据库管理服务,再有一个ES搜索服务。
那么我们怎么设计数据同步呢?
答案有2种:
1 用MQ来实现异步通知。
以下面为例:
2:binlog监听
我们来以第一种例子为例,实践一下:
管理项目中 mysql数据发生增删改查的时候,搜索项目中对ES来进行异步的消息同步。
消息中间件我们选择 rabbitMQ。
(不熟悉RabbitMQ的兄弟 可以去看我的专栏:rabbitMQ 养成记)
mysql管理服务作为生产者发送消息,ES管理服务作为消费者 监听消息,定义两个队列(增改,删除)和交换机绑定。 如果有数据变动 那么先更新数据库 然后再发消息给消费者 消费者拿到id之后 对ES进行更新即可:
创建队列绑定交换机(这个config既可以放在消费者里面也可以放在生产者里面)
@Configuration
public class MqConfig {
@Bean
public TopicExchange topicExchange(){
return new TopicExchange(MqContants.HOTEL_EXCHANGE,true,false);
}
@Bean
public Queue insertQueue(){
return new Queue(MqContants.HOTEL_INSERT_QUEUE,true);
}
@Bean
public Queue deleteQueue(){
return new Queue(MqContants.HOTEL_DELETE_QUEUE,true);
}
@Bean
public Binding bindInsertExchange(){
return BindingBuilder.bind(insertQueue()).to(topicExchange()).with(MqContants.HOTEL_INSERT_KEY);
}
@Bean
public Binding bindDeleteExchange(){
return BindingBuilder.bind(deleteQueue()).to(topicExchange()).with(MqContants.HOTEL_DELETE_KEY);
}
}
监听
@Component
public class HotelListener {
@Autowired
private IHotelService hotelService;
@RabbitListener(queues = MqContants.HOTEL_INSERT_QUEUE)
public void listenIandU(Long id){
hotelService.insertAndUpdateES(id);
}
@RabbitListener(queues = MqContants.HOTEL_DELETE_QUEUE)
public void listenD(Long id){
hotelService.deleteESById(id);
}
}
消费
@PostMapping
public void saveHotel(@RequestBody Hotel hotel){
hotelService.save(hotel);
rabbitTemplate.convertAndSend(MqContants.HOTEL_EXCHANGE,MqContants.HOTEL_INSERT_KEY,hotel.getId());
}
@PutMapping()
public void updateById(@RequestBody Hotel hotel){
if (hotel.getId() == null) {
throw new InvalidParameterException("id不能为空");
}
hotelService.updateById(hotel);
rabbitTemplate.convertAndSend(MqContants.HOTEL_EXCHANGE,MqContants.HOTEL_INSERT_KEY,hotel.getId());
}