最近在鼓捣将mysql数据推送到es中,看了常见的一些方法,例如用binlog同步数据的方式,但是原数据加在一起能有好几个T,所以一开始就没有启用binlog,最后没办法,还是通过去mysql查询的方式,一点点从mysql同步到es中。下面简单记录一下整个同步过程中做了哪些工作。
首先是处理源文件,如果源文件是压缩文件,则需要解压
tar -xzvf a.tgz
或者批量解压当前文件夹下的压缩文件
find -maxdepth 1 -name "*.tgz"|xargs -i tar xzvf {}
连接数据库
以显示的方式连接目标库:mysql -utest -p123456 database,test是用户名,123456是密码,database是要连接的数据库。实际上不推荐这样连接,因为会把密码暴露出来。
通过sql文件将数据导入mysql
source /test/test.sql;
使用这种方式导入数据,需要注意不能断开和服务器的连接,否则导入就会中断,所有数据就得重新导入。
后台导入mysql数据
为避免导入中断,可以通过shell脚本从后台导入数据:
1.文件名:test.sh
2.编写内容:
#!/bin/bash
mysql -u test --password=123456 --database=test_data </test/test.sql;
exit;
3.修改文件权限:chmod u+x test.sh
4.后台运行sh文件:nohup ./test.sh >./test.log 2>&1 &
实际遇到的问题:
不知道什么原因,后台进程被kill掉,导致数据导入中断,此时就只能通过前台导入的方式重新导入数据,继续使用上面的脚本导入会报错。
查看mysql库中所有表的大小和记录数
SELECT TABLE_NAME,DATA_LENGTH,INDEX_LENGTH,(DATA_LENGTH+INDEX_LENGTH) as length,TABLE_ROWS,concat(round((DATA_LENGTH+INDEX_LENGTH)/1024/1024,3), 'MB') as total_size FROM information_schema.TABLES WHERE TABLE_SCHEMA='database_name' order by length desc;
使用python将数据导入到es
from elasticsearch import Elasticsearch, helpers
# ElasticSearch 客户端初始化 这里连接的是es集群
es_hosts = ['1.2.3.4:10086']
es = Elasticsearch(hosts=es_hosts, http_auth=('test', test'), timeout=60,
max_retries=10, retry_on_timeout=True, maxsize=100)
def save_one_to_es(index_name, pid, body):
"""
向es推送一条数据
:param index_name: 索引名
:param pid: 如果不传id参数,会随机生成一个字符串作为_id
:param body: 需要推送的数据(dict)
:return:
"""
es.index(index=index_name, id=pid, body=body)
# es.index(index=index_name, body=body)
def save_more_to_es(index_name, json_list):
"""
同时推送多条数据
:param index_name: 索引名称
:param json_list: 多个json组成的列表
:return:
"""
actions = []
for idx, result in enumerate(json_list):
# 把id传给_id保持文档唯一性
action = {
'_index': index_name,
'_type': '_doc',
'_id': result['id'],
'_source': result
}
actions.append(action)
helpers.bulk(client=es, actions=actions)
还有一步没提到的是,如何查询海量的mysql数据。最开始使用的是limit方法,每次取1000条,但是越到后面查询就越慢;后来改为基于比较id的方式一点点查询数据,例如,最开始sql是这样的:
select id from test where id > 0 limit 1000;
通过上面的查询,拿到最大id(假设为9899),继续查询:
select id from test where id > 9899 limit 1000;
以此类推就可以拿到所有的数据。