概要
由于历史原因,A产品数据入Es库中字段默认都是keyword并没有区分字段类型属性,随着业务发展,需要更多数据格式,原有的keyword满足不了新需求,所以问题来了,新老数据字段属性产生了冲突,如何安全高效解决这个问题是本文内容。
一、问题分析
通过报错信息可以确定,当聚合查询时有两个索引拥有两个不一样类型。
使用kibana进行查看两个索引mapping(出问题的mapping肯定是我新升级后产生索引mapping和升级前的对比),如下图所示发现两个索引mapping类型a、b字段都对应不上,keyword和long起了冲突,验证了报错信息,开始修复。
二、修复过程
1、方案设计
采用大数据数据迁移中比较常用的ABA的方式来实现,将A索引内容同步到B索引中(B修改后的mapping),删除A索引并新建A索引及mapping,将B索引中数据同步回到A索引中即可,注意重新建A索引mapping时一定要用正确的字段类型的mapping,否则就白同步了。
2、实际操作
2.1、评估数据同步时长
一般正常数据大概1G数据100w条左右,而es正常同步速度5000~6000条/秒,也就是说同步1G数据大概需要3分钟左右速度(不同数据大小、机器性能及Es设置会略有不同)。
执行如下命令来查看:GET cat/indices/test*
可以很轻松评估出索引同步时间大概需要多久,如果是生产环境这个很重要,因为你要以一个最优的速度实现同步同时还不能影响线上环境使用。
2.3、B索引及mapping的创建
因为我要修复test_01索引,还不能比当前索引大,索引我采用前面加0,那么就是创建test_001索引。
获取test_01索引的mapping,然后进行修改为正确类型。
- 执行命令:GET test_01/_mapping
- 修改获取后的mapping字段
- 执行命令:POST test_001/message/_mapping {内容}
注意:禁止创建比当前索引数字大情况索引,系统会进行增量索引时报异常!
2.4、数据同步【A->B】
将索引test_01同步到索引test_001,执行如下命令即可:
# copy index
POST _reindex?refresh&wait_for_completion=false
{
"source": {"index": "test_01"},
"dest": {"index": "test_001"}
}
执行后会返回一个计划id
执行如下命令进行查看计划状态:
GET _tasks/M3duzBS0TdW4Sae8gmla7g:20187723082
Total总数据,created当前同步条数
备注:当不记得这个计划id情况执行如下命令可获取:
GET _tasks?detailed=true&actions=*reindex
2.5、A索引重构及数据同步【B->A】
在确认test_001索引数据同步完成,没有问题情况下
删除test_01索引,执行命令:DELETE test_01
创建test_01索引,执行命令:PUT test_01
test_001的mapping创建新索引test_01的mapping
执行恢复同步索引
# copy index
POST _reindex?refresh&wait_for_completion=false
{
"source": {"index": "test_001"},
"dest": {"index": "test_01"}
}
2.6、同步速度的调整
由于现场环境复杂,所以说需要调整好相应速率及性能占用,避免影响正常生成使用。
通过如下命令来调整同步速度:其中红色为计划id,黄色为每秒条数
POST _reindex/M3duzBS0TdW4Sae8gmla7g:20187173464/_rethrottle?requests_per_second=1000
当你想结束计划时,执行如下命令即可:
POST _tasks/M3duzBS0TdW4Sae8gmla7g:20187723082/_cancel
最后,别忘记删除test_001索引,全部操作完成
三、总结
1、在实际项目中可以去发现,当索引机制如果是对后面数字01和1不进行区分情况是可以只同步一次的,A索引数据同步到B索引,通过一些业务数据修改,是可以直接用B索引的没有问题,这个当然也是需要去亲力亲为去验证。
2、其实本篇文章虽然是说的两个字段属性冲突问题,但实际生产中可不仅可以同步字段属性,甚至做一些文本内容转换、数据格式转换、字段替换等等,可玩性和可拓展性很大。