==================针对线上使用场景主要做了以下操作==================
jvm调整
es初始化索引参数修改
"refresh_interval": “3s",
"durability": “async"
"flush_threshold_size": “800MB”
"sync_interval": "1s",
“Primaries": "3"
===============================================================
1.禁止swap,一旦允许内存与磁盘的交换,会引起致命的性能问题。 通过: 在elasticsearch.yml 中 bootstrap.memory_lock: true, 以保持JVM锁定内存,保证ES的性能。(目前为false)
2.当机器内存小于64G时,遵循通用的原则,50%给ES,50%留给lucene,设置为8G
3.GC设置原则:
保持GC的现有设置,默认设置为:Concurrent-Mark and Sweep (CMS),别换成G1GC,因为目前G1还有很多BUG。
4.索引的主分片数有什么用?设置小点有什么影响?
number_of_shards
每个索引的主分片数,默认值是 5 。这个配置在索引创建后不能修改。
number_of_replicas
每个主分片的副本数,默认值是 1 。对于活动的索引库,这个配置可以随时修改。
每次更改分片之后可以使用:GET my_test_index_004/_search_shards 来查询索引信息.
总结:TransLog主要作用是实时记录对于索引的修改操作,确保在索引写入磁盘前出现系统故障不丢失数据。tanslog的主要作用就是索引恢复,正常情况下需要恢复索引的时候非常少,它以stream的形式顺序写入,不会消耗太多资源,不会成为性能瓶颈。它的实现上,translog提供了对外的接口,translogFile是具体的文件抽象,提供了对于文件的具体操
问题:
新建templete,字段如果设置为keyword,聚合查询不会报错
初始化索引后,必须设置fileddata为true,否则聚合查询报错
PUT fktrait_h5_test/_mapping/doc
{
"properties": {
"sessionId": {
"type": "text",
"fielddata": true
},"appname": {
"type": "text",
"fielddata": true
},"channel": {
"type": "text",
"fielddata": true
},"cookieId": {
"type": "text",
"fielddata": true
},"curPage": {
"type": "text",
"fielddata": true
},"curUrl": {
"type": "text",
"fielddata": true
},"ipCity": {
"type": "text",
"fielddata": true
},"ipClient": {
"type": "text",
"fielddata": true
},"markName": {
"type": "text",
"fielddata": true
},"markType": {
"type": "text",
"fielddata": true
},"unit": {
"type": "text",
"fielddata": true
},"uploadTime": {
"type": "text",
"fielddata": true
},"userId": {
"type": "text",
"fielddata": true
}
}
}
GET /_template/fk_markdata_h5?pretty
删除一个模版:
curl -XDELETE 10.96.23.84:9200/_template/fk_markdata_h5
查看,可见删除模板成功:
curl -XGEThttp://10.96.23.84:9200/_template/fk_markdata_h5?pretty
直接复制索引到新的索引名称
POST localhost:9200/_reindex
{
"source": {
"index": "indexName"
},
"dest": {
"index": "newIndexName"
}
}
创建一个模版:
PUT /_template/fktrait_h5_routing_test
{
"order":1,
"index_patterns": ["fktrait_h5_routing_test*"],
"settings": {
"index": {
"number_of_shards": "3",
"number_of_replicas": "1",
"refresh_interval": "2s"
}
},
"mappings": {
"doc": {
"properties": {
"ipCity": {
"type": "keyword",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"channel": {
"type": "keyword",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"appname": {
"type": "keyword",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"@version": {
"type": "keyword",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"curUrl": {
"type": "keyword",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"ipClient": {
"type": "keyword",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"offset": {
"type": "long"
},
"userAgent": {
"type": "text",
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
}
},
"sessionId": {
"type": "keyword",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"uploadTime": {
"type": "keyword",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
" markType": {
"type": "keyword",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
" markName": {
"type": "keyword",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"userId": {
"type": "keyword",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"unit": {
"type": "keyword",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"@timestamp": {
"type": "date"
},
"curPage": {
"type": "keyword",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"ipProvince": {
"type": "keyword",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
}
}
},
"aliases": {}
}
将一个老索引的数据同步到新索引中:
可以采用elasticdump命令,前提是要用node新版本,在30.123上执行
elasticdump \
--input=http://10.96.23.84:9200/fktrait_h5_test\
--output=http://10.96.23.84:9200/fktrait_h5_test2 \
--type=data
es-sql执行时候,如何转换成DSL的?专程DSL之后是什么样的?\
Demo:
SELECT channel, COUNT(*) FROM fk_markdata_h5 GROUP BY channel ORDER BY COUNT(*) DESC
DSL:
get /fk_markdata_h5-*/_search?pretty
{
"size": 0,
"aggs": {
"group_by_state": {
"terms": {
"field": "channel"
}
}
}
}’
参数名称含义默认值
operator关联条件and,oror
Lenient查询时候数据类型不匹配无法转换时候报错false
zero_terms_query主要为了解决查询条件中包含停止词,避免过滤之后查询不到数据none
cutoff_frequency区分常用高频词,指定一个分界文档频率值
auto_generate_synonyms_phrase_query不明白什么意思FALSE
在实际工作场景中:一般字段类型都设置为keyword,那么最好用terms查询,避免分词
1.将字段设置成keyword的时候查询的时候已有的值不会被分词
2.如果将字段设置为text类型,是会被分词的,采用term查询,输入单个分词可以查询到,但是如果输入完整的值则查询不到
3.match和term的区别:
- term查询keyword字段,term不会分词,keyword也不会分词,需要完全匹配
term查询text字段,term不会分词,text字段会分词,所以查询条件必须是text字段分词后的某一个
match查询keyword字段,match会被分词,而keyword不会被分词,match的需要和keyword的完全匹配才可以
match查询text类型,match会分词,text也会分词,只要match的分词结果和text的分词结果相同就会匹配
4.
1)match_phrase匹配keyword字段。
这个同上必须跟keywork一致才可以。
只有这种情况才是成功的。
2)match_phrase匹配text字段。
match_phrase是分词的,text也是分词的。match_phrase的分词结果必须在text字段分词中都包含,而且顺序必须相同,而且必须都是连续的。
这是成功的。
如果不是连续的,就会失败。
4.
1)query_string查询keyword类型的字段,试过了,无法查询。
失败的,无法查询。
2)query_string查询text类型的字段。
和match_phrase区别的是,不需要连续,顺序还可以调换。
成功。
这样也是可以的。
例子:
select count(distinct sessionId) as count FROM fk_markdata_h5-* where userId=39836912 and uploadTime >= '2019-04-02 00:00:00' and uploadTime <= '2019-04-02 16:07:53' and sessionId <>’null'
DSL:
GET fk_markdata_h5-*/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"userId": {
"query": "39836912"
}
}
},
{
"range": {
"uploadTime": {
"from": "2019-04-02 00:00:00",
"to": "2019-04-02 16:07:53"
}
}
}
]
}
}
}
es的索引是什么规则分发到分片上的?能否按照用户id来分发数据?
分片策略?
es路由到分片的算法过程
shard= hash(routing)% number_of_primary_shards
routing是一个字符串,默认是索引的_id值,也可以自己定义。
(假如routing设置为用户ID呢?)
这个routing字符串通过哈希函数生成一个数字,然后除以主切片的数量得到一个余数(remainder),
余数的范围永远是0到number_of_primary_shards - 1,这个数字就是特定文档所在的分片。
假设:一个index有2个primary shard,p0和p1,hash函数产出的值对这个index的primary shard的数量求余数最后的结果就是0或者1,也就是说这个document就放在那个分片上
primary shard数量不可变的原因?
导致查询时候,定位不在原来的shard上买,查询不到document
logstash 中指定routing的字段,然后插入到es中,es中不做任何设置。
下面是我logstash的output部分:
output {
if [type] == "dsq-info" {
elasticsearch {
hosts => ["10.1.0.12:9200"]
index => "%{[fields][index]}-%{+YYYY.MM.dd}"
routing => "%{userId}" ###这里是关键字,你选择使用那个字段做索引。 }
}
}
然后在kifana中指定routing查询。
GET fktrait_h5_routing_test-2019.04.01/_search
{
"query": {
"terms": {
"_routing": [ "20105601" ]
}
}
}
官网地址:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-routing-field.html
在初始化索引时候,可以设置是否必须输入routing
如果设置必须输入,在logstash或者其它方式写入数据的时候,必须指定routing,这仅仅代表es进行索引时候配置的路由值,请记住索引时候不支持多个路由配置,而定义查询时候可以配置多个路由
PUT my_index2
{
"mappings": {
"_doc": {
"_routing": {
"required": true
}
}
}
}
PUT my_index2/_doc/1
{
"text": "No routing value provided"
}
思考:应该是在初始化索引时候指定路由的值是userId
==================================
总结:logstash写入es的时候指定routing为userid,这样在DSL查询时候指定查询路由,可以减少查询数据量,提高查询效率