栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

Elasticsearch报错out of range of long完整解决流程

Elasticsearch报错out of range of long完整解决流程

定位问题

业务侧的数据类型是uint64位,通过filebeat传输到logstash,然后输出到elasticsearch。运营QA等人员在kibana上查数据发现会有丢失查不到的情况发现es的日志有大量的报错如下:

Caused by: com.fasterxml.jackson.core.JsonParseException: Numeric value (18446744073709551615) out of range of long (-9223372036854775808 - 9223372036854775807)

和开发确认相关字段长度是uint64,但是es索引使用默认mapping的数据类型是long,导致业务数据id长度超过了mapping的字段长度没法储存。 解决方案

需要修改索引的mapping字段类型,但是es的索引一旦建立就不能修改了,只能重建索引和迁移数据搭建测试环境,还原现有索引和mapping docker 部署ELK(7.5.1),还原线上报错

安装elasticsearch

docker  pull elasticsearch:7.5.1
docker run -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d -p 9200:9200 -p 9300:9300  -v /data/es/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /data/es/data:/usr/share/elasticsearch/data  --name ES 2bd69c322e98

其中es的配置如下

cat elasticsearch.yml |grep -v '^$' |grep -v '^#'
path.data: /data/es/data
path.logs: /data/es/log
xpack.security.enabled: true
indices.query.bool.max_clause_count: 4096
indices.fielddata.cache.size: 10%
indices.breaker.fielddata.limit: 50%
indices.breaker.request.limit: 50%
xpack.monitoring.collection.enabled: true

安装kibana

docker pull kibana:7.5.1
docker run -d --name=kibana --link 0d1b2dfb511f:elasticsearch -p 5601:5601 kibana:7.5.1
#docker run --link可以用来链接2个容器,使得源容器(被链接的容器)和接收容器(主动去链接的容器)之间可以互相通信,并且接收容器可以获取源容器的一些数据,如源容器的环境变量。
#0d1b2dfb511f是es的容器id
#elasticsearch是给es取得name
#如果kibana中的配置有修改的,可以通过docker exec -it kibana /bin/bash进入容器修改完成,重启kibana

其中kibana的配置如下

cat kibana.yml  |grep -v '^$' |grep -v '^#'
server.name: kibana
server.host: "0"
elasticsearch.hosts: [ "http://localhost:9200" ]
xpack.monitoring.ui.container.elasticsearch.enabled: true
i18n.locale: "zh-CN"

安装logstash

docker pull logstash:7.5.1
docker run -p 5044:5044 --name logstash --link 0d1b2dfb511f:elasticsearch -d docker.elastic.co/logstash/logstash:7.5.1

其中logstash的配置如下

logstash.yml 
http.host: "0.0.0.0"
xpack.monitoring.elasticsearch.hosts: [ "http://ES所在机器的IP:9200" ]

pipeline的配置如下

pipeline/logstash.conf 
input {
  beats {
    port => "5044"
  }
}

filter {
        json {
        source => "message"
    }
}

output {
	elasticsearch {
        hosts => ["ES机器IP:9200"]
        index => "ES索引名"
	}
}

安装完ELK后,可以通过kibana界面进行配置和操作了

#考虑到要复现问题,先设置es的日志级别到debug
PUT /_cluster/settings
{
    "transient":{
        "logger._root":"DEBUG"
      
    }
    
  }
PUT test  #创建索引
GET test/_settings  #查看索引配置
PUT test/_settings  #配置索引参数
{
  "index.mapping.total_fields.limit":10000
}
POST /test/_mapping #提交索引映射,这个mapping是从正式环境copy来的,由于mapping很长,就截取关键部分(数据字段不匹配的部分)
{
      "properties" : {
        "@timestamp" : {
          "type" : "date"
        },
        "@version" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "agent" : {
          "properties" : {
            "ephemeral_id" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
        "test_user_id" : {
              "type" : "long"
            },
        "test_id" : {
              "type" : "long"
            },
        "tags" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "ts" : {
          "type" : "float"
        }
      }
}    
GET /test/_mapping #查看映射

去产生日志的业务机器起一个filebeat,向logstash发送日志文件,filebeat配置如下图(output中的hosts就是logstash的ip)

配置完成之后,logstash中的pipeline的output,修改index,然后进行重启,这样可以接收到日志数据了。这些做完后在ES中查看到和正式环境一样的报错了,字段长度超出mapping的long类型,如下
测试环境解决问题

新建索引,mapping字段类型修改,从long改为double(容纳的数据更长)

PUT test02  #创建索引
GET test02/_settings  #查看索引配置
PUT test02/_settings  #配置索引参数
{
  "index.mapping.total_fields.limit":10000
}
POST /test02/_mapping #提交索引映射,这个mapping是从正式环境copy来的,由于mapping很长,就截取关键部分(数据字段不匹配的部分)
{
      "properties" : {
        "@timestamp" : {
          "type" : "date"
        },
        "@version" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "agent" : {
          "properties" : {
            "ephemeral_id" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
        "test_user_id" : {
              "type" : "double"
            },
        "test_id" : {
              "type" : "double"
            },
        "tags" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "ts" : {
          "type" : "float"
        }
      }
}    
GET /test02/_mapping #查看映射

数据迁移,从旧索引迁移到新索引(最好停掉log进行迁移)

POST _reindex
{
  "source": {"index": "test"},
  "dest": {"index": "test02"}
}

等待迁移完成,然后logstash中的pipeline修改output,把index从test改为test02,重启logstash

input {
  beats {
    port => "5044"
  }
}

filter {
        json {
        source => "message"
    }
}

output {
        elasticsearch {
        hosts => ["ES的ip:9200"]
        index => "test02"
        }
}

可以在kibana中查看有文档数了
kibana的setting中创建对应的索引
在Discover中查询对应的数据,发现可以查到id为18446744073709551615这么大的结果了
ES相关概念 集群(cluster)

代表一个集群,集群中有多个节点(node),其中有一个为主节点,这个主节点是可以通过选举产生的,主从节点是对于集群内部来说的。es的一个概念就是去中心化,字面上理解就是无中心节点,这是对于集群外部来说的,因为从外部来看es集群,在逻辑上是个整体,你与任何一个节点的通信和与整个es集群通信是等价的。 索引(index)

ElasticSearch将它的数据存储在一个或多个索引(index)中。用SQL领域的术语来类比,索引就像数据库,可以向索引写入文档或者从索引中读取文档,并通过ElasticSearch内部使用Lucene将数据写入索引或从索引中检索数据。 文档(document)

文档(document)是ElasticSearch中的主要实体。对所有使用ElasticSearch的案例来说,他们最终都可以归结为对文档的搜索。文档由字段构成。比如每一条商品信息,就是一个文档。 映射(mapping)

所有文档写进索引之前都会先进行分析,如何将输入的文本分割为词条、哪些词条又会被过滤,这种行为叫做映射(mapping)。一般由用户自己定义规则。字段的数据类型、属性、是否索引、是否存储等特性。 类型(type)

每个文档都有与之对应的类型(type)定义。这允许用户在一个索引中存储多种文档类型,并为不同文档提供类型提供不同的映射。类型是模拟mysql中的table概念,一个索引库下可以有不同类型的索引,比如商品索引,订单索引,其数据格式不同。不过这会导致索引库混乱,因此未来版本中会移除这个概念。 分片(shards)

代表索引分片,es可以把一个完整的索引分成多个分片,这样的好处是可以把一个大的索引拆分成多个,分布到不同的节点上。构成分布式搜索。分片的数量只能在索引创建前指定,并且索引创建后不能更改。5.X默认不能通过配置文件定义分片。 副本(replicas)

代表索引副本,es可以设置多个索引的副本,副本的作用一是提高系统的容错性,当个某个节点某个分片损坏或丢失时可以从副本中恢复。二是提高es的查询效率,es会自动对搜索请求进行负载均衡。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/710451.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号