我虽然穷,但是我爱学习呀。
当然,如果我有一个亿,我愿意放弃这个爱好,去玩耍。
开场白:
Lucene:一个基于Java的搜索库,采用了基于倒排表的设计原理,高效地实现文本查找。底层采用了分段的存储模式,在读写时避免了锁的出现
Elasticsearch:对 Lucene 进行了封装,对外提供 RESTful API
Kibana:负责以图表的形式呈现数据
Logstash:动态数据收集管道
Beats:轻量型数据采集器,负责从成百上千或成千上万台机器和系统向 Logstash 或 Elasticsearch 发送数据
1 为什么要用 Elasticsearch?
1.1 站内搜索用SQL就能实现,为什么要用 Elasticsearch 呢?
先来看看我们用SQL来搜索的话,有什么缺点:
- SQL没有相关度排名,如综合排序。而ES内部是有一个打分机制的。
- SQL搜索结果没有关健字高亮显示
- SQL搜索有时较慢,尤其是数据库不在本地时,超慢
1.2 模糊查询
假设有一张书籍表book,根据书籍名称从中检索一些书籍时,用MySQL实现,你可能会这样写SQL:
SELECT * FROM book WHERE book_name LIKE '%关键词%'
这样做,理论上是可以搜到一些数据的,比如和用户输入的关键词完全匹配的就可以,如果 颠倒了词的顺序,LIKE关键词肯定是匹配不到了。
例:
搜索一本书籍名称为 “黑萌影帝妙探妻” 的书,使用 SQL
select * from r_read_book where book_name like '%影帝黑%'
搜索结果为空。而使用 ES 可以搜索出相应的书籍
GET book/_search
{
"query": {
"match": {
"book_name": "影帝黑"
}
}
}
另外,LIKE是全表扫描的一个操作,如果你的数据量较小,还好说,但如果你数据量在百万、千万甚至更多的时候,耗时将是不可想象的,而且 DB 的 like操作会导致 SQL 注入黑洞。如:
select * from book where book_name like '%1%';drop table book;#%'
标红的为输入值,#表示注释
注入的独立语句
drop table book;
会造成删表
2 有了 ElasticSearch 还需要 MySQL 吗?
通常,我们可以使用 ES 来实现自己的站内搜索引擎,但还是推荐大家使用 MySQL 来做原始数据的存储,然后基于 MySQL 在上层部署我们的 ES 中间件来实现我们的搜索引擎。主要原因是,MySQL 虽然在数据全文检索方面显得有些力不从心,但是因为它的事务功能特性,可以保证不会出现脏数据。而ES对事务方面并无建树,所以不是很适合存储原始数据。当然,你可以运用双写的策略,一方面利用 MySQL 保证原始数据的安全性,另一方面,利用ES的搜索力量。更推荐的是将两个中间件直接结合起来,同时使用 ES 查询数据,并结合 MySQL 做数据的增删差改,具体实现细节,要根据实际的需求来制定最优的解决方案。
2.1 ElasticSearch 作为主要的后端系统
适用于新启动的项目
2.2 将 Elasticsearch 添加到现有的系统
对于一个正在运作的复杂系统,但想加入搜索功能,可以采用同步机制
例子:
有一家在线零售商店,商品的信息都存在 SQL 数据库中,需要快速且相关性良好的搜索,于是安装了 Elasticsearch。为了索引数据,需要部署同步机制,既可以是 Elasticsearch 的插件,也可以是自行构建的定制化服务。同步的机制可以将每个商品对应的数据拉取出来,并将其索引到 Elasticsearch 中,每个商品存储为一篇 Elasticsearch 的文档。信息的插入或更新仍可以在 SQL 数据库上进行,可以使用 Elasticsearch 仅来处理搜索。保持 Elasticsearch 更新最近的变化取决于同步的机制。
3 开始动手了
3.1 安装与查看插件(Mac)
(1)安装 elasticsearch
下载压缩包,解压,进入bin,运行 elasticsearch
cd elasticsearch-7.15.1
bin/elasticsearch
访问:Elasticsearch 9200 端口
查看本地安装好的插件,安装指定的插件
(2)安装 Kibana
下载压缩包,解压,进入bin,运行 elasticsearch
cd kibana-7.15.1-darwin-x86_64
bin/kibana
访问:Kibana 5601端口
(3)安装Logstash
下载压缩包,解压,进入bin,运行 logstash,修改或创建 logstash.conf,导入测试数据,参考
cd logstash-7.15.1/bin
sudo ./logstash -f /Users/vincentwen/Downloads/logstash-7.15.1/bin/logstash.conf
3.2 基本概念
3.2.1 Index 索引
An index is a collection of documents that have somewhat similar characteristics. For example, you can have an index for customer data, another index for a product catalog, and yet another index for order data.
ES 索引是一类文档的集合,类似于数据库。每个索引都有自己的 Mapping 定义,用于定义包含的文档的字段名和字段类型。
索引的不同语意
名词:ES 的索引,用于保存文档
动词:保存一条文档到 ES 的过程,也叫索引(Indexing)
3.2.2 Document 文档
Elasticsearch 是面向文档型数据库,ES 索引里的单条记录称为文档,类似于 MySQL 里的一条记录。文档可以是播放器里的一首歌,一篇 PDF 文档的具体内容,一部电影的具体信息......
文档会被序列化成 JSON 格式,保存在 ES 中,如:
{ "name" : "John",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ] }
每条文档都有对应的元数据,用于标注文档的相关信息
3.2.3 Type 类型
Document 可以分组,比如 book
这个 Index 里面,可以按类型分组(言情和玄幻),也可以按作者分组。这种分组就叫做 Type,它是虚拟的逻辑分组,用来过滤 Document。
如上,type 类型中的 book_name 字段与 author 类型中的 book_name 字段是被存储在同一个字段中,而且两个 book_name 字段在这两种映射类型中都有相同的定义,如类型都是 text。
当你希望在一个索引中的两个映射类型,一个映射类型中的 deleted 字段映射为一个日期数据类型的字段,而在另一个映射类型中的 deleted 字段映射为一个布尔数据类型的字段,这就会失败。
而在一个关系型数据库中,表之间是相互独立的。一个表中的列与另一个表中同名的列没有关系。
7.0 开始,一个索引只能创建一个 Type - '_doc'
3.2.4 Elasticsearch和关系型数据术语大致的对照
3.2.5 节点
节点是一个 Elasticsearch 的实例,本质上就是一个 JAVA 进程。一台机器上可以运行多个 Elasticsearch 进程,但生产环境一般建议一台机器上只运行一个 Elasticsearch 实例。
每一个节点都有名字,通过配置文件配置,或者启动时指定。节点启动之后会分配一个 UID,保存在 data 目录下。
Master-eligible nodes
每个节点启动,默认就是一个 Master eligible 节点,它可以参加选举流程,成为 Master 节点。
Mster Node
第一个节点启动时,它会将自己选举成 Master 节点。每个节点上都保存了集群的状态,只有 Master 节点才能修改集群的状态信息。
3.3 基本操作
(1) 查看 ES 的基本信息
GET /
(2) 新建一个 Index,并指定需要分词的字段。
PUT /book
{
"mappings": {
"properties": {
"book_name": { "analyzer": "standard","type": "text"},
"author": { "type": "keyword" },
"desc": { "analyzer": "standard","type": "text"},
"comment_count":{"type":"integer"}
}
}
}
上面代码中,首先新建一个名称为book
的 Index,里面有 3 个字段
bookName:类型为text文本,指定了一个标准的分词器,用于全文搜索。
author:类型为keyword关键字,不需要分词,用于聚合查询,统计分析。
desc:类型为text文本,指定了一个标准的分词器,用于全文搜索。
(3) 添加文档,book 为索引,_doc 为类型。7.x 版本,一个索引只有一个类型。
POST book/_doc/1
{
"book_name": "大人物的小萌妻",
"author": "秋如意",
"desc": "她跟他相差了十岁,她,在学校,视做平庸无奇的眼镜妹;在家族里,被人笑没人要的书呆子;他,商界大佬对他俯首称臣,帝国上将奉他为座上宾,偏偏有了交集!大叔,我会好好做你的小萌妻!你可不能反悔!大叔,爱你无悔!",
"comment_count":57
}
POST book/_doc/2
{
"book_name": "黑萌影帝妙探妻",
"author": "犬犬",
"desc": "第一回合,他被她推得头破血流,第二回合,他被她摔得满目晕眩,但他始终知道,她就是那个他要的女人。",
"comment_count":107
}
POST book/_doc/3
{
"book_name": "西晋小厨师",
"author": "乱石兰竹",
"desc": "乱世将临,且看卫平揽财富,聚美人,收天下英雄,扶大厦于将倾。",
"comment_count":11
}
(4) 根据 id 查看文档
GET book/_doc/1
(5) 修改文档用 PUT,修改文档 id 为 1 的文档
PUT book/_doc/1
{
"book_name": "大人物的小萌妻",
"author": "秋如意",
"desc": "她跟他相差了十岁",
"comment_count":57
}
(6) 根据字段匹配文档,再做修改。如下:找到 “author” 为 “秋如意” 的文档,再修改其 “desc” 字段值。
POST book/_update_by_query
{
"script":{
"source":"ctx._source.desc = params.desc",
"lang":"painless",
"params":{
"desc":"她跟他相差了十岁"
}
},
"query":{
"match":{
"author":"秋如意"
}
}
}
(7) 根据书籍名称匹配查询
GET book/_search
{
"query": {
"match": {
"book_name": "影帝黑"
}
}
}
(8) 多个字段匹配查询
GET book/_search
{
"query": {
"bool":{
"must":[
{"match":{
"author":"秋如意"
}},{
"match":{
"book_name":"小"
}
}
]
}
}
}
(9) 统计数量
GET book/_count
{
"query": {
"bool":{
"must":[
{"match":{
"author":"秋如意"
}},{
"match":{
"book_name":"小"
}
}
]
}
}
}
(10) 按某字段排序
GET user/_search
{
"query": {
"range":{
"age":{
"gte":30,
"lte":40
}
}
},"sort":[
{
"age":{
"order":"desc"
}
}
]
}
(11) 查询结果高亮显示
GET book/_search
{
"query" : {
"match": { "book_name": "影帝黑" }
},
"highlight" : {
"fields" : {
"book_name" : {}
}
}
}
(12) 聚合查询
GET book/_search
{
"size": 0,
"aggs": {
"range": {
"field": "comment_count",
"ranges": [
{
"from": 100,
"to": 110
},
{
"from": 50,
"to": 60
}
]
}
}
}
(13) 分组查询,如下按 “author” 分组查询
GET book/_search
{
"size": 0,
"aggs": {
"author": {
"terms":{
"field":"author"
}
}
}
}
3.4 SpringBoot 集成 Elasticsearch
参考:
elasticsearch入门 springboot2集成elasticsearch 实现全文搜索
结合spring boot和mysql快速实现elasticsearch7简单功能
3.5 MySQL的数据同步到 ES
全量同步:搭建好 ES 后,把 MySQL 的数据一次性同步过去
增量同步:MySQL 产生新的数据后同步到 ES,包括:新插入的数据,更新了老数据,删除了老数据
灵魂拷问:你会怎样去实现捏?
方式一:
- select * from table,然后在程序中遍历,对应生成一条条文档插入到 ES。中途又有了新数据,咋办捏?每一次同步都保留最大的 last_update_time,select * from table where updat_time >= last_update_time。
方式二:
- 在操作数据库的 CRUD 方法里对应加上 ES 的CRUD,这会导致代码,业务,数据耦合度过高
方式三:召唤中间件
3.5.1 Binlog 订阅
二进制日志 binlog:binlog是记录所有数据库表结构变更(例如CREATE、ALTER TABLE…)以及表数据修改(INSERT、UPDATE、DELETE…)的二进制日志。binlog不会记录SELECT和SHOW这类操作,因为这类操作对数据本身并没有修改,但你可以通过查询通用日志来查看MySQL执行过的所有语句。
阿里巴巴 MySQL binlog 增量订阅&消费组件Canal
为毛我还没过上小康生活捏?因为 ES 没学好。
4 Elasticsearch 为什么快?
为什么Elasticsearch/Lucene检索可以比MySQL快?
4.1 索引是个啥
索引(indexing):就是把一个 关键码 与它对应的 数据记录位置 相关联的过程,不同的索引有不同的关联方式。
4.2 关系型数据库的 B-Tree 索引
二叉树查找效率是logN,同时插入新的节点不必移动全部节点,所以用树型结构存储索引,能同时兼顾插入和查询的性能。因此在这个基础上,再结合磁盘的读取特性(顺序读/随机读),传统关系型数据库采用了B-Tree/B+Tree这样的数据结构。
4.2.1 MyISAM索引
MyISAM表的索引和数据是分离的,索引保存在”表名.MYI”文件内,而数据保存在“表名.MYD”文件内。
4.2.2 InnoDB索引
首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。
4.3 Lucene 索引
4.3.1 Inverted Index(倒排索引)
Lucene 实现快速搜索的核心就是倒排索引,那什么是倒排索引呢?
这里每一行是一个document,每个document都有一个docid,那么给这些document建立的倒排索引
一个字段有一个自己的倒排索引。18,20 这些叫做 term,而 [1,3] 就是posting list。Posting list就是一个 int 的数组,存储了所有符合某个 term 的文档 id。
4.3.2 Term Dictionary
为了能快速找到某个term,将所有的term排序 排序后:Carla, Sara, Elin, Ada, Patty 用二分查找的方式查找 term,这个就是 term dictionary。 有了 term dictionary 之后,可以用 logN 次磁盘查找得到目标。 为了尽量少的读磁盘,但是磁盘的随机读操作仍然是非常昂贵的(一次random access大概需要10ms的时间),有必要把一些数据缓存到内存里。但是整个 term dictionary 本身又太大了,无法完整地放到内存里。 于是就有了 term index。
4.3.3 Term Index
term index 实际为一棵 tire 树,只存 term 的一些前缀。 通过 term index 可以快速地定位到 term dictionary 的某个偏移量, 然后从这个位置再往后顺序查找。 再加上一些压缩技术,使得用内存缓存整个 term index 变成可能。
4.3.4 索引流程
当我们在搜索框输入商品名称,点击查询。es的分词器会对商品名称进行分词,形成一个或多个term。然后根据 term 去查询内存中的 term index(一棵前缀树),通过 term index 可以定位到 term 在 term dictionary 中的位置,找到对应的倒排列表(存的文档id,地址偏移量等),拿到相关的文档id,根据文档ID找到对应的文档数据返回。
4.4 总结
现在我们可以回答 “ 为什么 Elasticsearch/Lucene 检索可以比MySQL快 ” 了。
Mysql 只有 term dictionary 这一层,是以树的方式存储在磁盘上的。检索一个 term 对磁盘进行若干次的 random access(随机访问)。而 Lucene 在 term dictionary 的基础上添加了 term index 来加速检索,term index 以树的形式缓存在内存中。从 term index 查到对应的 term dictionary 的 block 位置之后,再去磁盘上找 term,大大减少了磁盘的 random access 次数。
额外值得一提的两点是:前缀树
term index 在内存中是以 FST(finite state transducers)的形式保存的,其特点是非常节省内存。Term dictionary 在磁盘上是以分 block 的方式保存的,一个 block 内部利用公共前缀压缩,比如都是Ab开头的单词就可以把Ab省去。这样 term dictionary 可以更节约磁盘空间。
5 分片
5.1 概念
如果一个索引具有很大的数据量,它的数据量可能会超出单个节点的容量限制(硬盘容量),而且单个节点数据量过大,执行性能也会随之下降,每个搜索请求的执行效率都会降低。
为了解决上述问题, Elasticsearch 提出了分片的概念,索引将划分成多份,称为分片(shard)。默认情况下,一个索引具有一个主分片,一个主分片有一个副分片。(7.x版本之前,一个索引默认有 5 个主分片和 1 个副分片)。
一个 Elasticsearch 索引是分片的集合。Elasticsearch 中的分片其实就是 Lucene 索引,一个 Lucene 索引最大可存放2,147,483,519 个文档。一个分片默认存储原始文档的内容,再加上一些额外的信息,如词条字典和词频。
此外,一个 Lucene 索引由一个或多个 segment 构成,每个 segment 本质上就是一个倒排索引。
下图为 lucene 索引存储结构概念图
在lucene 中,同时还会维护一个文件 commit point,用来记录当前所有可用的 segment,当我们在这个 commit point 上进行搜索时,就相当于在它下面的 segment 中进行搜索,每个 segment 返回自己的搜索结果,然后进行汇总返回给用户。
当索引一个文档的时候,文档会被存储到一个主分片中。那 Elasticsearch 如何知道一个文档应该存放到哪个分片中呢?真相就是下面的公式:
shard = hash(routing) % number_of_primary_shards
routing 是一个可变值,默认是文档的 _id ,也可以设置成一个自定义的值。 routing 通过 hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards (主分片的数量)后得到余数 。这个分布在 0 到 number_of_primary_shards-1 之间的余数,就是我们所寻求的文档所在分片的位置。
5.2 分片的作用
分片的主要用处:水平划分数据;多个分片并行执行,提高性能
副本分片主要用处:数据备份;副本分片本身也是一个功能齐全的独立分片,当有查询请求时,既可以在主分片中完成查询,也可以在副本分片中完成查询,当然数据添加、更新的操作只能在主分片中完成。
副本分片与主分片需要分配在不同的节点上,一是为了更好的均衡负载,不同节点上二是节点发生故障时,主分片和副本分片一起故障,没法保证高可用性。所以 Elasticsearch 集群最好要有 2 个节点或以上。
6 分词
7 TF-IDF 打分
8 自动补全 Suggesters
public ServiceResult<List<String>> suggest(String prefix) {
CompletionSuggestionBuilder suggestion = SuggestBuilders.completionSuggestion("suggest").prefix(prefix).size(5);
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("autocomplete", suggestion);
SearchRequestBuilder requestBuilder = this.esClient.prepareSearch(INDEX_NAME)
.setTypes(INDEX_TYPE)
.suggest(suggestBuilder);
logger.debug(requestBuilder.toString());
SearchResponse response = requestBuilder.get();
Suggest suggest = response.getSuggest();
if (suggest == null) {
return ServiceResult.of(new ArrayList<>());
}
Suggest.Suggestion result = suggest.getSuggestion("autocomplete");
...
List<String> suggests = Lists.newArrayList(suggestSet.toArray(new String[]{}));
return ServiceResult.of(suggests);
}
9 项目实战
9.1 用户数据多维度检索
需求与背景:实现用户信息的多维度检索,需要聚合用户账户信息、用户基础信息、用户会员信息、用户标签信息、业务扩展等信息。索引的docId是:rootSaasId(店铺ID) + Uid(用户ID),用户数量为 4273 3996,拆分为 1024 张表。
{
"settings": {
"number_of_shards": "10",
"number_of_replicas": "1",
"index.refresh_interval": "1s"
},
"mappings": {
"properties": {
"rootSaasId": {
"type": "keyword"
},
"uid": {
"type": "keyword"
},
"memberCode": {
"type": "keyword"
},
"nickName": {
"type":"text",
"analyzer":"ik_max_word",
"search_analyzer":"ik_max_word"
},
"headUrl": {
"type": "text",
"index": false
},
"personSign": {
"type": "text"
},
"gender": {
"type": "byte"
},
"phone": {
"type": "keyword"
},
"birthday": {
"type": "keyword"
},
"status": {
"type": "byte"
},
"address": {
"type": "text"
},
"email": {
"type": "keyword"
},
"nameInfo": {
"type": "text"
},
"busiIdentity": {
"type": "keyword"
},
"certificateList": {
"type": "text"
},
"versionId": {
"type": "long"
},
"sourceDetail": {
"type": "text"
},
"createTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
},
"updateTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
},
"extList": {
"type": "nested",
"properties": {
"saasId": {
"type": "keyword"
},
"extKey": {
"type": "keyword"
},
"extValue": {
"type": "keyword"
},
"createTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
},
"updateTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
},
"channelAccountList": {
"type": "nested",
"properties": {
"channelAccount": {
"type": "keyword"
},
"channelType": {
"type": "keyword"
},
"userGroup": {
"type": "keyword"
},
"bindTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
},
"memberIdentifyList": {
"type": "nested",
"properties": {
"saasId": {
"type": "keyword"
},
"levelType": {
"type": "keyword"
},
"levelId": {
"type": "keyword"
},
"cardNo": {
"type": "keyword"
},
"status": {
"type": "keyword"
},
"updateTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
},
"createTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
},
"tagList": {
"type": "nested",
"properties": {
"saasId": {
"type": "keyword"
},
"tagIdList": {
"type": "keyword"
}
}
}
}
}
}
9.2 房屋信息多维度搜索
需求背景:实现一个房屋搜索网站
索引 json
{
"settings": {
"number_of_replicas": 0
},
"mappings": {
"house": {
"dynamic": false,
"properties": {
"houseId": {
"type": "long"
},
"price": {
"type": "integer"
},
"lastUpdateTime": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
},
"cityEnName": {
"type": "keyword"
},
"subwayLineName": {
"type": "keyword"
},
"street": {
"type": "keyword"
},
"suggest": { // 对应自动补全功能
"type": "completion"
},
"traffic": {
"type": "text",
"index": "analyzed"
}
}
}
}
}
索引模板
public class HouseIndexTemplate {
private Long houseId;
private Date createTime;
private Date lastUpdateTime;
private String cityEnName;
private int direction;
private List<String> tags;
private List<HouseSuggest> suggest;
private BaiduMapLocation location;
...
}
异步构建索引
涉及关键字的搜索查 es,否则直接查 DB
public ServiceMultiResult<HouseDTO> query(RentSearch rentSearch) {
// 涉及关键字搜索查es
if (rentSearch.getKeywords() != null && !rentSearch.getKeywords().isEmpty()) {
ServiceMultiResult<Long> serviceResult = searchService.query(rentSearch);
if (serviceResult.getTotal() == 0) {
return new ServiceMultiResult<>(0, new ArrayList<>());
}
return new ServiceMultiResult<>(serviceResult.getTotal(), wrapperHouseResult(serviceResult.getResult()));
}
// 否则查db
return simpleQuery(rentSearch);
}
10 Elasticsearch 的优缺点
某电商项目通过orderNo分库分表,但是C端⽤户需要通过数据库查询所有订单的场景,使用es会有哪些优缺点?
⽅案简述 | 说明 | 优点 | 缺点 | 适用场景 |
es | 数据同步到es | 各种数据维度都⽀持查询 | 1.新加组件成本⾼ 2.实时性较差 | 1.实时性 要求不 ⾼ 2. 多维 度查询 |
关系表 冗余 | 新增⼀张表单 独存储⽤户id和orderNo的关系 | 1.实现简单 2.各种维度都⽀ 持, 都可以建关 系表 3.实时性⾼ | 1.多⼀次查询性能较差 2.新加数据成本⾼ | 1.性能要 求不⾼ 2.实时性要求⾼ |
基因法插⼊ | 把待查询字段 的末尾N位插⼊ 分库分表字段 的值中; 例如本案例, 可 以将userId的后 N位插⼊订单ID 的后N位 | 1.实现简单 2.成本低 3.性能⾼ | 需要分库分表 字段的值⽀持 和特定字段的 1对1随机组合拼装; | 分库分 表字段 的值⽀ 持和特 定字段 的1对1随 机组合 拼装; |
10.1 优势
(1) 横向可扩展性:只需要增加一台服务器,做一点儿配置,启动一下ES进程就可以并入集群;
(2) 分片机制提供更好的分布性:同一个索引分成多个分片(shard),采用分而治之的方式来提升处理效率;
(3) 高可用:提供复制(replica)机制,一个分片可以设置多个复制,使得某台服务器宕机的情况下,集群仍旧可以照常运行,并会把由于服务器宕机丢失的复制恢复到其它可用节点上;类似于 HDFS 的复制机制(HDFS中默认是3份复制)。
10.2 不足
- 不支持事务
- 同步延时,ES的数据同步来源于MySQL,会出现不同程度的同步延时
- 数据丢失,当同步服务出现异常或ES不可⽤,可能会出现ES数据丢失
- 并发度低,在压测过程中,发现从es查询的接⼝性能较差,不能⽀持⾼并发,容易出现cpu100%和es集群卡死的情况