实时同步
双写
当对数据库进行数据的增删改操作时,同时对 ES 进行相同的操作,并把两个操作放到一个事务中。
@Transactional(rollbackFor = Exception.class)
public void update(OrderDTO orderDTO) {
//更新本地数据库
updateDb(orderDTO);
//远程更新ES
updateEs(orderDTO);
}
缺点首先是需要改代码,有侵入性,还有就是存在不一致的情况。并且在本地事务中发生了外部调用,大大拖长了事务,白白占用数据库链接,影响整体的吞吐量。
消息队列异步更新
借助消息队列(如 Kafka、RabbitMQ)来实现异步更新。当数据库发生数据变更时,业务代码把变更消息发送到消息队列,然后由专门的消费者从队列中消费消息并更新 ES。以 Kafka 为例,数据库更新操作触发后,生产者把变更消息发送到 Kafka 主题,消费者从主题中获取消息并更新 ES。
定时同步
全量任务
如果对数据变更的实时性要求不高,可以设置定时任务扫表, 然后批量更新ES,定期将数据库中的全量数据同步到 ES。
增量同步
定期检查数据库中自上次同步之后发生变更的数据,并将这些变更同步到 ES。可以利用数据库的日志(如 MySQL 的 Binlog)来记录数据的变更信息,然后通过工具(如 Canal)解析 Binlog,将变更数据同步到 ES。
目前业内比较流行的方案是基于binlog监听进行增量同步