并发版本控制
-
在并发量大的情况下,同时修改某一条数据会出现并发冲突
-
解决方法可以加锁:乐观锁,以及悲观锁
-
1、先查询数据 127.0.0.1:9200/example/_doc/1 //获取当前的_seq_no以及_primary_term参数 2、执行修改操作 127.0.0.1:9200/example/_doc/1?if_seq_no=4&if_primary_term=1 //这里携带版本参数即可实现乐观锁
-
冲突的情况:
-
{ "error": { "root_cause": [ { "type": "version_conflict_engine_exception", "reason": "[1]: version conflict, required seqNo [4], primary term [1]. current document has seqNo [25] and primary term [1]", "index_uuid": "Mf_ArU05Rlm2F2kFfimYCQ", "shard": "0", "index": "example" } ], "type": "version_conflict_engine_exception", "reason": "[1]: version conflict, required seqNo [4], primary term [1]. current document has seqNo [25] and primary term [1]", "index_uuid": "Mf_ArU05Rlm2F2kFfimYCQ", "shard": "0", "index": "example" }, "status": 409 }
-
倒排索引理解
-
ES是一个倒排索引进行检索的,倒排索引指的是:通过关键字,查询主键id,随后查询关联的内容
-
(某个单词在一个文档或一组文档中的存储位置的映射)
//文档--单词的对照 doc1 中国、美国 doc2 英国、法国、中国
// 单词 --- 文档 中国 doc1、doc2 美国 doc1 英国 doc2 法国 doc2
- 由此可以得出 搜索“中国”的关键字,则匹配的文档有:doc1、doc2,这就是最简单的倒排理解
- 开发中一般都是以文档的内容进行分词,中文可以用ik分词器,而英文则使用默认。其中每分一个词对应的就是多个关联的文档,也就是一个词对应多个文档,一对多的关系
分词器理解
- 英文分词:
- 输入文本、词汇分割、词汇过滤(去除停顿词)、词干提取、大小写转化、结果输出
- 中文分词:
- 词典匹配分词法
- 语义理解分词法
- 词频统计分词法
布尔检索模型
-
其就是对检索的文本进行条件表达式操作
-
主要的有:and、or、not,其中的优先级关系为,not>and>or
-
//示例 doc1 doc2 doc3 doc4 人工 1 1 1 0 谷歌 0 1 0 1 开源 0 1 0 1 大会 1 0 0 0 查询包含谷歌、开源不包括,大会 谷歌and开源not大会 0101 and 0101 not 1000 //可以把不包含取反,做为包含计算 0111 变为: 0101 and 0101 and 0111 得出: doc2以及doc4是符合条件的
Elasticsearch优点
- 分布式的搜索引擎和数据分析引擎
- 全文检索,结构化检索,数据分析
- 对海量数据进行近实时的处理
- RestFul api驱动
核心概念
实时 读写速度毫秒级别
进实时 秒级别,读写速度有一定的延迟
离线 分钟级别,响应很慢
- 集群
- 包含多个节点,每个节点属于哪个集群是通过一个配置(集群名称,默认是elasticsearch)来决定的,对于中小型应用来说,刚开始一个集群就一个节点很正常。集群的目的为了提供高可用和海量数据的存储以及更快的跨节点查询能力。
- 节点
- 集群中的一个节点,节点也有一个名称(默认是随机分配的),节点名称很重要(在执行运维管理操作的时候),默认节点会去加入一个名称为“elasticsearch”的集群,如果直接启动一堆节点,那么它们会自动组成一个elasticsearch集群,当然一个节点也可以组成一个elasticsearch集群
- 索引
- 包含一堆有相似结构的文档数据,比如可以有一个客户索引,商品分类索引,订单索引,索引有一个名称。
一个index包含很多document,一个index就代表了一类类似的或者相同的document。比如说建立一个product index,商品索引,里面可能就存放了所有的商品数据,所有的商品document。
- 包含一堆有相似结构的文档数据,比如可以有一个客户索引,商品分类索引,订单索引,索引有一个名称。
- 类型
- 每个索引里都可以有一个或多个type,type是index中的一个逻辑数据分类,每一个type里面,都会包含一堆document。相当于一个表
- 文档
- document 是es中的最小数据单元,一个document可以是一条客户数据,一条商品分类数据,一条订单数据,通常用JSON数据结构表示,每个index下的type中,都可以去存储多个document。一个document里面有多个field,每个field就是一个数据字段。相当于一行数据
- 分片
- 单台机器无法存储大量数据,es可以将一个索引中的数据切分为多个shard,分布在多台服务器上存储。有了shard就可以横向扩展,存储更多数据,让搜索和分析等操作分布到多台服务器上去执行,提升吞吐量和性能。相当于mysql分区
- 副本
- 任何一个服务器随时可能故障或宕机,此时shard可能就会丢失,因此可以为每个shard创建多个replica副本。replica可以在shard故障时提供备用服务,保证数据不丢失,多个replica还可以提升搜索操作的吞吐量和性能。
- 分片和副本的数可以在出啊关键索引的时候决定。在索引创建之后,可以在任何时候动态改变副本的数量,但是事后不能改变分片的数量
ik分词器安装及使用
-
下载链接:https://github.com/medcl/elasticsearch-analysis-ik/releases 前提条件对应版本下载
-
在plugins目录下新建ik目录,讲安装包解压到该目录
-
使用:
-
//创建索引,给指定字段使用分词器 "title": { "type": "text", //必须是text类型 "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } }, "analyzer" : "ik_max_word", "search_analyzer": "ik_max_word", "index" : true } // 这样创建好之后,以后的查询默认会使用分词器 IK分词器包含两种analyzer,一般用ik_max_word ik_max_word:会将文本做最细粒度的拆分 ik_smart:会做最粗粒度的拆分
-
本地测试:随便拿一个索引
-
127.0.0.1:9200/example/_analyze //域名/索引/固定格式
{
“analyzer”:“ik_smart”,
“text”:“五羊雪糕真的好好吃”
}
-
路由机制
-
当索引一个文档的时候,文档会被存储到一个主分片中,这个过程是根据hash算法决定的
-
shard_num = hash(_routing) % num_primary_shards
-
其中 _routing 是一个可变值,默认是文档的 id的值 ,也可以设置成一个自定义的值。 _routing 通过 hash 函数生成一个数字,然后这个数字再除以 num_of_primary_shards (主分片的数量)后得到余数 。这个分布在 0 到 number_of_primary_shards-1 之间的余数,就是我们所寻求的文档所在分片的位置。这就解释了为什么我们要在创建索引的时候就确定好主分片的数量并且永远不会改变这个数量:因为如果数量变化了,那么所有之前路由的值都会无效,文档也再也找不到了,同时数据所有的分片上的平局分布,不会出现补均衡的情况
-
因为默认情况下,Elasticsearch使用文档的ID(类似于关系数据库中的自增ID),如果插入数据量比较大,文档会平均的分布于所有的分片上,这导致了Elasticsearch不能确定文档的位置,所以它必须将这个请求广播到所有的N个分片上去执行, 这种操作会给集群带来负担,增大了网络的开销;
映射
-
分为动态映射和静态映射。其就是创建索引时,为字段创建类型
-
动态映射
-
在向ES中插入文档数据时, ES会根据每个新field可能的数据类型, 自动为其配置type等mapping信息
-
JSON数据 ES中的数据类型 null 不会添加字段 true or false boolean floating point number double integer long object object array 依赖于第一个非null得值 string 如果通过了date检测,则为date,如果通过了numeric检测,则为Number、text或者keyword
-
开启dynamic mapping动态映射策略
-
true 开启 —— 遇到陌生字段时, 进行动态映射 false 关闭 —— 忽略遇到的陌生字段 strict 遇到陌生字段时, 作报错处理 PUT blog_user { "mappings": { "_doc": { "dynamic": "strict", // 严格控制策略 "properties": { // "name": { "type": "text" }, "address": { "type": "object", "dynamic": "true" // 开启动态映射策略 } } } } }
-
-
静态映射
- 是在创建索引时候手工指定索引映射,和SQL创建表结构一样
ELK
- ELK=elasticsearch+Logstash+kibana
- elasticsearch:后台分布式存储以及全文检索
- logstash: 日志加工、“搬运工” 。服务器端数据处理管道,它同时从多个源中提取数据,进行转换,然后将其发送到类似 Elasticsearch 的 “存储” 中
- kibana:数据可视化展示。
- ELK架构为数据分布式存储、可视化查询和日志解析创建了一个功能强大的管理链。 三者相互配合,取长补短,共同完成分布式大数据处理工作
集群管理
搭建节点
-
1、确定节点的数量
-
2、确定master节点数
脑裂
- 脑裂问题其实就是同一个集群的不同节点对于整个集群的状态有不同的理解(不一致的状态),导致操作错乱,类似于精神分裂
- 发现脑裂
- 通过命令查看集群的状态 : 127.0.0.1:9200/_cluster/health
- 正常情况下,访问每一个节点,对集群中的状态返回应该是一致的。不一致的信息表示集群中不同节点对master节点的选择出现了问题。导致集群不能正常工作
- 产生原因
- 网络
- 由于某些节点之间的网络通信出现问题,导致一些节点认为master节点已经挂了,所以有重新选举了新的master节点,从而导致集群信息混乱
- 节点负载过大:由于master节点与data节点都是混在一起的,有可能master节点的负载过大,导致对应的es实例停止响应,这时一部分节点会一位master节点已经挂掉从而重新选举,导致多master节点运行。
- 解决办法
- 在config配置找到Elasticsearch.yml,修改discovery.zen.minimum_master_nodes属性,推荐值是(N/2)+1,其中N是节点的数量
- 修改discovery.zen.ping_timeout属性,默认值是3秒,应当增加等待时间
索引规划
- 常见索引默认分片数是5,副本数为1
- 查看分片和副本数:127.0.0.1:9200/索引/_settings
运行过程
- 请求 - 分发请求到不同节点 - 对不同的节点的分片进行搜索 - 搜索结果合并 - 返回
分布式集群
案例模拟
1、准备好3台虚拟机,以及环境安装好
2、获取三台服务器ip
3、修改配置文件 config/elasticsearch.yml
cluster.name: myes ###保证三台服务器节点集群名称相同
node.name: node-1 #### 每个节点名称不一样 其他两台为node-2 ,node-3
network.host: 192.168.212.180 #### 实际服务器ip地址
discovery.zen.ping.unicast.hosts: ["192.168.212.184", "192.168.212.185","192.168.212.186"] ##多个服务集群ip
discovery.zen.minimum_master_nodes: 1
4、关闭防火墙 systemctl stop firewalld.service
5、启动所有服务器,打开主节点 *号表示为master节点
集群api
- 百度了,不写了