ElasticSearch的作用
ElasticSearch属于Nosql,是一款非关系型数据库,主要用于数据的全文检/搜索
Mysql不具备快速搜索海量数据的能力.
强事务控制
redis做数据缓存,降低mysql的压力
数据库排行榜: https://db-engines.com/en/
ElasticSearch引入倒排索引技术,来解决传统关系型数据库无法快速搜索海量数据的能力,ES的特性就是利用索引进行快速的查询,对于ES技术,“万物皆索引”来形容可以说是最为贴切了;
传统的关系型数据库的查找流程,即遍历查找,假若我们现在拥有500w个数据需要检索,直接拜拜;
ES提供了倒排索引的机制,对比形象的理解的就是新华字典里,我们通过前面的偏旁部首和拼音,可以很快就找到我们不认识的汉字,想想如果这种搜索方式不存在,那我们需要一个字一个字查找整本约9w字的新华字典!这个耗时是无法接受的;
检索数据流程
ES的底层
ES的底层同样来自给这个世界带来无限可能的Apache公司,Apache早前提供了一套用于全文检索和搜寻的开源程序库,Lucene;
Lucene提供了一个简单却强大的应用程序接口(API),能够做全文索引和搜寻,在Java开发环境里Lucene是一个成熟的免费开放源代码工具;
面向服务编程:
ElasticSearch是一个web服务,当ElasticSearch启动时,就相当于启动了一个web项目,直接通过浏览器访问即可.遵循RestFul风格的路径,返回json格式的数据
安装与使用
傻瓜式安装然后双击elasticsearch.bat文件即可启动。可以看到日志中的IP和端口信息:
Kibana
ElasticSearch是一个web服务,但是没有提供图形化界面来操作。因此我们需要安装Kibana,方便学习。
中文界面需要进入其配置文件config→kibana.yml中,配置"zh-CN"
ES-headmaster
ES-headmaster是一个可视化的ES数据库界面,通过访问端口,我们可以监控我们的数据信息;
安装时必须提供node.js软件,解压后,cmd→cnpm install→npm start
分词器
我们需要引入中文分词器来使用ES技术;
解压后,将ik文件夹放在ES的plugins文件夹下;
动态模板
基本语法
默认映射规则不一定符合我们的需求,我们可以按照自己的方式来定义默认规则。这就需要用到动态模板了。
动态模板的语法:
- 模板名称,随便起
- 匹配条件,凡是符合条件的未定义字段,都会按照这个mapping中的规则来映射,匹配规则包括:
match_mapping_type
:按照数据类型匹配,如:string匹配字符串类型,long匹配整型match
和unmatch
:按照名称通配符匹配,如:t_*
匹配名称以t开头的字段
- 映射规则,匹配成功后的映射规则
凡是映射规则中未定义,而符合2中的匹配条件的字段,就会按照3中定义的映射方式来映射
示例
# 动态模板
PUT heima3
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word"
}
},
"dynamic_templates": [
{
"strings": {
"match_mapping_type": "string",
"mapping": {
"type": "keyword"
}
}
}
]
}
}
这个动态模板的意思是:凡是string类型的字段,统一按照 keyword来处理。
接下来新增一个数据试试:
POST /heima3/_doc/1{
"title":"超大米手机",
"images":"http://image.leyou.com/12479122.jpg",
"price":3299.00}
然后查看映射:
GET /heima3/_mapping
结果:
{
"heima3" : {
"mappings" : {
"dynamic_templates" : [
{
"strings" : {
"match_mapping_type" : "string",
"mapping" : {
"type" : "keyword"
}
}
}
],
"properties" : {
"images" : {
"type" : "keyword"
},
"price" : {
"type" : "float"
},
"title" : {
"type" : "text",
"analyzer" : "ik_max_word"
}
}
}
}
}
路由计算&分片控制
我们在ES中进行插入和查询数据的时候,是遵循一种被称为路由计算的规则
的;
这种规则也是为什么ES的主分片决定好之后就无法再修改,但是副本却可以动态修改的原因;
因为主分片是查询数据的关键,我们需要通过主分片数来决定数据存储的位置,而副本只是起到备份的作用,所有的数据还是围绕着主分片进行的,如果我们允许动态修改主分片数,那么路由运算就会被打乱,这将造成此前已经插入的数据无法查询到的窘境;
路由计算:hash(id)%主分片数量=对应的主分片所以库
我们在查询的时候,因为ES集群的主副特性,其实查任意一个node都是没有问题的,但是有时候某些node太忙了,那这个时候此node就会转移请求给别的空闲的node,这就是我们说的ES在查询数据时实施的策略,分片控制,以轮询的概念,负载均衡访问的数量给每个节点;
高亮搜索的实现
高亮是在搜索结果中把搜索关键字标记出来,因此必须使用match这样的条件搜索。
elasticsearch中实现高亮的语法比较简单:
GET /heima/_search
{
"query": {
"match": {
"title": "手机"
}
},
"highlight": {
"pre_tags": "<em>",
"post_tags": "</em>",
"fields": {
"title": {
}
}
}
}
Source筛选
默认情况下,elasticsearch在搜索的结果中,会把文档中保存在_source
的所有字段都返回。
如果我们只想获取其中的部分字段,我们可以添加_source
的过滤
直接指定字段
示例:
GET /heima/_search
{
"_source": ["title","price"],
"query": {
"term": {
"price": 2699
}
}
}
返回的结果:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "heima",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"price" : 2699.0,
"title" : "小米手机"
}
}
]
}
}
指定includes和excludes
我们也可以通过:
- includes:来指定想要显示的字段
- excludes:来指定不想要显示的字段
二者都是可选的。
示例:
GET /heima/_search
{
"_source": {
"includes":["title","price"]
},
"query": {
"term": {
"price": 2699
}
}
}
与下面的结果将是一样的:
GET /heima/_search
{
"_source": {
"excludes": ["images"]
},
"query": {
"term": {
"price": 2699
}
}
}
Docker中设置开机自启指令
ES集群
-
什么是集群?为什么需要ES集群?
集群可以简单理解为多台服务器,以ES为例,作为一个非关系型数据库,用户在访问的时候,加入我们的服务器宕机了,很可能因此就失去了这个用户,为了保证服务的高可用,我们为ES建立一个集群,这样,在某台服务器宕机的时候,我们就可以保证用户依然能够正常进行访问等业务; -
那服务器配多少台比较合适呢?
服务器配置的数量,从经验上讲,我们应该配置的总数量一定要呈单数,因为服务器理论上要符合50%原则,即宕机数不能超过服务器数量的一半,如果超过了,除了硬件问题等无法预知的事件,其实就是集群搭建是不合理的,服务器数量保持在单数,可以很好的规避一半原则; -
配置这么多台服务器,我们的数据每台都放吗?还是有其它的解决方案,因为如果每台都放,成本会太大了吧,能说说看吗?
对于这个事情,以ES集群为例,我们可以采用数据分片的分布式存储方式来解决,就好比一本新华字典的结果页分成等额的份,分别存储在各节点上; -
如果一个服务器宕机,数据不就不完整了吗,这要怎么解决呢?
这个时候,我