
// 读取要导入数据的文件
BufferedReader br = new BufferedReader(new FileReader(
"D:\\test\\test.txt"))
String json = null
int count = 0
// 开启批量插入
BulkRequestBuilder bulkRequest = client.prepareBulk()
while ((json = br.readLine()) != null) {
bulkRequest.add(client.prepareIndex("test", "all")
.setSource(json))
// 每一千条提交一次
if (count % 1000 == 0) {
bulkRequest.execute().actionGet()
System.out.println("提交了:" + count)
}
count++
}
bulkRequest.execute().actionGet()
System.out.println("插入完毕")
br.close()
登录后复制
运行后发现一个问题,我100多万条的数据,导入到es中怎么生成了1000多万条,而且还是在没有完全导入的情况下
然后用小批量数据导入到es,再把这些数据导出来,发现有好多重复的数据
为什么会重复呢,原因是在每一千条提交一次代码这块,第一次一千条提交了,并没有把bulkRequest置空,所以第二次提交的时候,会提交两千条,包括第一次已经提交的一千条,然后我们自己也没有设置_id,所以es会自动给数据生成一个_id,即使是重复的数据,搞清楚了原因,下面来说解决方法,主要有两种:
第一种就是在提交了一千条后,对bulkRequest进行重置,因为bulkRequest并没有重置的方法,所以可以新建一个bulkRequest,类似于重置,具体代码如下:
// 读取要导入数据的文件
BufferedReader br = new BufferedReader(new FileReader(
"D:\\test\\test.txt"))
String json = null
int count = 0
// 开启批量插入
BulkRequestBuilder bulkRequest = client.prepareBulk()
while ((json = br.readLine()) != null) {
bulkRequest.add(client.prepareIndex("test", "all")
.setSource(json))
// 每一千条提交一次
if (count % 1000 == 0) {
bulkRequest.execute().actionGet()
//此处新建一个bulkRequest,类似于重置效果
bulkRequest = client.prepareBulk()
System.out.println("提交了:" + count)
}
count++
}
bulkRequest.execute().actionGet()
System.out.println("插入完毕")
br.close()
登录后复制
第二种就是自己设置_id,确保每一条数据只有一个_id,这样的话,即使数据重复了,因为_id是一样的,所以es会进行更新,这样的话并没有从根源上解决数据重复的问题,只是重复数据会更新,这样的话效率会慢,具体代码如下:
// 读取要导入数据的文件
BufferedReader br = new BufferedReader(new FileReader(
"D:\\test\\test.txt"))
String json = null
int count = 0
// 开启批量插入
BulkRequestBuilder bulkRequest = client.prepareBulk()
while ((json = br.readLine()) != null) {
//设置_id为count
bulkRequest.add(client.prepareIndex("test", "all",
String.valueOf(count)).setSource(json))
// 每一千条提交一次
if (count % 1000 == 0) {
bulkRequest.execute().actionGet()
//此处新建一个bulkRequest,类似于重置效果
System.out.println("提交了:" + count)
}
count++
}
bulkRequest.execute().actionGet()
System.out.println("插入完毕")
br.close()
登录后复制
建议使用第一种方法,效率会快很多。
https://www.elastic.co/guide/en/elasticsearch/guide/2.x/near-real-time.html
https://www.elastic.co/guide/en/elasticsearch/guide/2.x/merge-process.html
1、数据存储可靠性保证原理
1.1 translog机制
当一个文档写入Lucence后是存储在内存中的,即使执行了refresh *** 作仍然是在文件系统缓存中,如果此时服务器宕机,那么这部分数据将会丢失
当进行文档写 *** 作时会先将文档写入Lucene,然后写入一份到translog,写入translog是落盘的
tips:如果对可靠性要求不是很高,也可以设置异步落盘,可以提高性能,由配置index.translog.durability和index.translog.sync_interval控制
tips:translog是追加写入,因此性能比较好
先写入Lucene再写入translog。原因是写入Lucene可能会失败,为了减少写入失败回滚的复杂度,因此先写入Lucene
1.2 flush *** 作
refresh_interval定时触发 或当translog达到index.translog.flush_threshold_size(默认512mb),ES会触发一次flush *** 作:先执行refresh *** 作将buffer中的数据生成segment,然后调用lucene的commit方法将所有内存中的segment fsync到磁盘,最后会清空translog中的数据(6.x版本为了实现sequenceIDs,不删除translog) 。
1.3 merge *** 作
refresh *** 作会产生大量的小segment,因此产生的每个文件都会消耗文件句柄,内存,CPU 使用等各种资源。更重要的是每个查询请求都要顺序检查每个segmentsegment越多检索会越慢.
ES会运行一个检测任务,在后台把近似大小的segment合并成一个新的大segment,并删除旧segment
1.4、多副本机制
ES有多副本机制(默认是1个副本),一个分片的主副分片不能分片在同一个节点上,进一步保证数据的可靠性。
2、ES写索引的流程
1. ES和solr都是作为全文搜索引擎出现的。都是基于Lucene的搜索服务器。
2. ES不是可靠的存储系统,不是数据库,它有丢数据的风险。
3. ES不是实时系统,数据写入成功只是trans log成功(类似于MySQL的bin log),写入成功后立刻查询查不到是正常的。因为数据此刻可能还在内存里而不是进入存储引擎里。同理,删除一条数据后也不是马上消失。写入何时可查询?ES内部有一个后台线程,定时将内存中的一批数据写入到存储引擎,此后数据可见。默认后台线程一秒运行一次。该线程运行的越频繁,写入性能越低。运行的频率越低,写入的性能越高(不会无限高)。
4.目前已知的单ES集群可以存储PB级别的数据,不过这个就非常费劲了。TB级别数据没压力。
5.如果使用ES官方提供的jar包访问,需要JDK1.7及以上。
6.使用对应的版本访问ES server。如果ES server端的版本是1.7,那么请使用ES 1.7的client。如果ES server是2.1,请使用2.1的client。
7. ES索引存在Linux服务器的文件系统之上(背后是文件系统,不是类似于HDFS的分布式文件系统)
8. ES Java client是线程安全的,全局构建一个即可满足读写需求,不要每次都创建ES client。每次访问ES都构建新的es client即会抛出次异常。
9.非常不建议使用ES的动态识别和创建的机制,因为很多情况下这并非你所需要。推荐的做法是在写数据之前仔细的创建mapping。
10. 强烈不建议在ES中使用深分页。可能会导致集群不可用。
11.ES是静态分片,一旦分片数在创建索引时确定那么后继不能修改。
12.ES里提供了type,很多人以为type是物理表,一个type的数据是独立存储的;但是在ES内部并不是这样,type在ES内部仅仅是一个字段。所以在很多数据能分为独立index的情况下,不要放到一个index里用type去分。只有嵌套类和父子类的情况下使用type才是合理的。
13.ES并不提供原生的中文分词的能力。有第三方的中文分词的插件,比如ik等。Ik是个toy分词器,有严肃的分词需求的话,请在使用ES之前使用独立的分词器分好词后向ES写入。
14.ES中的index,首先会进行分片,每一个分片数据一般都会有自己的副本数据,ES分配分片的策略会保证同一个分片数据和自己的副本不会分配到同一个节点上。当集群中的某一节点宕机后,ES的master在ping该节点时通过一定的策略会发现该节点不存活;会开启ES的恢复过程
15.ES没有update的能力。所有的update都是标记删除老文档,然后重新insert一条新文档。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)