1.ES简介
Elasticsearch,简称ES,是一个基于Lucence的开源搜索引擎。如果单单使用Lucence,不仅要使用Java开发,还要深入了解检索的知识。ES通过简单的RESTful API隐藏了Lucence的复杂性; ES是一个分布式文档数据库,文档中每个字段均可被索引,而且每个字段的数据均可被搜索,可以将ES部署成集群,它会自动寻找属于同一集群的节点; ES5.x版本引入了 Painless(废弃了2.x版本的groovy脚本),这是一种安全而又强大的脚本语言,允许操作各种数据类型,使用脚本是执行复杂搜索的终极方式。此次ES之旅就以5.6.9版本开始!
2.ES核心概念
2.1.node
node,即节点。是一个正在运行着的Elasticsearch实例,属于集群的一部分,可以存储数据,并参与群集的索引和搜索功能。默认情况下,节点名称为一个随机的通用唯一标识符(UUID),并默认被分配到名为“elasticSearch”的集群。节点名称对管理很重要,目的是要确定网络服务器对应的ES群集节点,可以通过群集名配置节点以连接特定的群集。
2.2.cluster
cluster,即集群。是一组具有相同 cluster.name 的ES节点集合。一个集群由一个唯一集群ID确定,并指定一个集群名(默认为“elasticsearch”)。该集群名非常重要,因为节点可以通过这个集群名加入群集,一个节点只能是群集的一部分。
修改cluster.name的步骤:
到elasticsearch安装的目录下的../config/elasticsearch.yml,将cluster.name注释解开,修改它的值
2.3.index
index,即索引。ES将数据存储于一个或多个索引中,索引是具有类似特性的文档的集合。类比传统的关系型数据库,索引相当于SQL中的一个数据库,或者一个数据存储方案(schema)。索引由其名称(必须为全小写字符)进行标识,并通过引用此名称完成文档的创建、搜索、更新及删除操作。一个ES集群中可以按需创建任意数目的索引.
2.4.type
type,即类型。是索引内部的逻辑分区(category/partition),其意义完全取决于用户需求。因此,一个索引内部可定义一个或多个类型(type)。一般来说,类型就是为那些拥有相同的域的文档做的预定义。例如,在索引中,可以定义一个用于存储用户数据的类型,一个存储日志数据的类型,以及一个存储评论数据的类型。很多情况下,会把ES的类型type比作SQL中的表,其实是不对的!SQL中的表是相互独立的,表与表之间的字段互不影响。而ES中同一个index下的type,同名的字段在Lucene内部是由同一个字段支持,即user索引下的student类型和teacher类型的id字段,其实是同一个字段,这就要求它们必须是同一种数据类型。这边可以自己尝试,在同一个index下创建两个type,都带有id字段,其中一个type的id字段类型设为text,另一个type的id字段设为integer,ES会报错:
因此:在ES6.0以上版本中创建的索引只允许存在一个type;在ES7.0中类型type概念将被彻底删除.(在ES5.x中创建的多映射类型的索引在ES6.x中将如以前一样可用,为了过渡)
2.5.document
document,即文档。是Lucene索引和搜索的原子单位,它是包含了一个或多个域的容器,基于JSON格式进行表示。文档由一个或多个域组成,每个域拥有一个名字及一个或多个值,有多个值的域通常称为“多值域”。每个文档可以存储不同的域集,但同一类型下的文档至应该有某种程度上的相似之处。相当于数据库的“记录”,文档以唯一ID标识并存储于ES中。一个文档不仅仅包含数据,它还包含3个元数据:
2.6.shard
shard,即分片。是ES底层的工作单元,一个分片就是一个Lucence实例,它自身就是一个完整的搜索引擎。单台机器无法储存大量的数据,ES将一个索引( 即数据库 )的数据切分为多个shard,分布在多台服务器上存储。分片分为主分片(primary shard)和副分片(replica shard),一般主分片简称为primary,副分片简称为replica。
主分片:
在索引建立时就已确定主分片数,不能修改,默认为5个。索引任意一个文档都归属于一个主分片,所以主分片的数目决定着索引能够保存的最大数据量。
副分片:
一个副本分片只是一个主分片的拷贝,默认1个主分片对应1个副分片,随时可以修改。副分片作为硬件故障时保护数据不丢失的冗余备份,并为搜索和返回文档等读操作提供服务。默认情况:一个Index,有10个shard,其中5个主分片,5个副分片;注意:主分片和它的副分片不能同时存在于一台服务器上(防止宕机都失效)。
2.7.mapping
mapping,即映射,是定义文档的字段的存储类型和索引方式的过程,ES带有dynamic mapping(自动映射)功能,能自动映射我们put或post进去的文档,但对于一些复杂数据类型如地理位置就需要我们手动定义。
可以使用mapping来定义:
①应将哪些字符串字段视为全文字段
②哪些字段包含数字,日期或地理位置
③用于控制动态添加字段的映射的自定义规则
...等等
2.8.analyzer
analyzer,即分词。数据在存储时,ES会对文档各字段的值进行倒排索引,这就要涉及到将一段句子分为各个短语,这个过程就是分词,能够执行分词的程序成为分词器。例如:原句子:"The QUICK brown foxes jumped over the lazy dog!",分词器会将该句子分成不同的短语,对短语进行小写转换,删除频繁的停用词(“the”)并将术语缩减为它们的词干(foxes→fox,jumped→jump,lazy→lazi)最后,原句子被分为如下短语并将这些短语添加至倒排索引中:[ quick, brown, fox, jump, over, lazi, dog ];
由此可见,不同分词器对同一个句子分词得到的结果并不一样,这就要求了ES在对文档建立倒排索引使用到的分词器要和对客户端发起的查询子句分词的分词器要一样,这样才能搜索得到。这就解释了为啥同一个查询条件在对不同字段查询时,得到的结果不一样,原因就是同一个查询条件在不同字段查询时,ES会选取不同的分词器去分词,得到的结果不一样,导致搜索的结果也不一样
3.ES语法简介
ES可以使用curl命令访问,也可以使用Restful API访问
3.1.curl语法
VERB:表示HTTP方法:GET, POST, PUT, HEAD, DELETE
PROTOCOL:表示http或者https协议
HOST:表示ES集群中的任何一个节点的主机名,本地为localhost
PORT:表示ES HTTP服务所在的端口,默认为9200
PATH:表示API路径(例如_count将返回集群中文档的数量),也可以包含多个组件,例如_cluster/stats 或 _nodes/stats/jvm
QUERY_STRING:表示可选的查询请求参数,例如 pretty 参数将使请求返回更加美观易读的JSON数据
BODY:表示一个JSON格式的请求主体(如果请求需要的话)
例如:
①查看ES是否启动:
curl -XGET 127.0.0.1:9200
②请求ES的数据:
curl -XGET 'http://localhost:9200/_count?pretty' -d '
{
"query": {
"match_all": {}
}
}
Linux环境自带curl,如果window环境,则需要先安装curl插件,也可以使用sense插件来访问,相同效果的写法为:
GET /_count
{
"query": {
"match_all": {}
}
}
3.2.Restful语法
使用sense插件(谷歌浏览器搜索,新版谷歌浏览器貌似没有,如果有需要的可以找我拿)查询ES,不过更推荐使用kibana访问ES
4.ES内部原理
4.1.路由算法
ES的路由算法:shard = hash(routing) % number_of_primary_shards
(通过对routing计算hash值,然后将此值对主分片数量求余,求余的结果决定放置的分片)
routing -- 默认_id,也可以手动指定,ES大部分API都支持routing参数
number_of_primary_shard -- ES的主分片总数量
例子:
假如集群在初始化的时候有5个primary shard,在里边加入一个document { id=5 } ,假如hash(5)=23,这时该document 将被加入 (shard=23%5=3)P3这个分片上。如果随后我们给es集群添加一个primary shard ,此时就有6个primary shard,当我们GET id=5 ,这条数据的时候,es会计算该请求的路由信息找到存储他的 primary shard(shard=23%6=5) ,根据计算结果定位到P5分片上。而我们的数据在P3上。所以es集群无法添加primary shard,但是可以扩展replicas shard。
4.2.协调节点
ES是一个集群,当发起一个文档搜索or 文档增删请求时,接收客户端请求的ES节点很有可能不是存放该文档的节点,这种情况下接收请求的节点就是协调节点(coordinating node)。它通过路由算法计算存放文档的节点,将请求转发到真正可以处理的节点上,当节点处理完以后,将结果返回给协调节点,然后节点再返回给客户端。特别地,当文档请求时增删改时,协调节点只会转发给存放主分片的节点,在主分片节点处理完以后,同步数据到对应的复制分片节点,在这两步都完成后协调节点才会返回结果给客户端
4.3.一致性机制
wait_for_active_shards是ES5.x版本取代consistency 的新参数,它可以指定:如果必需数量的活动分片副本(注意是replica shard)不可用,则写入操作必须等待并重试,直到必需的分片副本已启动或发生超时。默认写入操作仅等待主分片在继续之前处于活动状态,即wait_for_active_shards = 1,通过设置index.write.wait_for_active_shards,可以在索引设置中动态覆盖此默认值:
当分片副本不足时Elasticsearch会等待更多的分片出现。默认等待一分钟。如果需要,你可以设置timeout参数让它终止的更早:100表示100毫秒,30s表示30秒。
4.4.轮询调度
Round Robin(中文翻译为轮询调度)。ES采取round-robin随机轮询算法,将对同一个文档的多次请求,负载均衡地分发到primary shard和replica shard上。例如:可能对一个文档有4次请求,2次给primary shard处理,2次给replica shard处理..
5.小结
5.1.index不同含义
索引(index)这个词在Elasticsearch中有着不同的含义:
①索引(名词),一个索引(index)就像是RDBS中的数据库,它是相关文档存储 的地方,index的复数是indices 或indexes;
②索引(动词),表示把一个文档存储到索引(名词)里,以便它可以被检索或者查询。这很像SQL中的 INSERT 关键字,差别是,如果 文档已经存在,新的文档将覆盖旧的文档;
5.2.倒排索引
倒排索引,也称为反向索引,是搜索引擎的基础数据结构。用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。倒排索引实例:
①假设有5个文档,文档编号和文档内容如下图所示:
如果按照关系型数据库,则为文档编号建立索引,通过文档编号可以快速查找文档内容,这就叫正向索引;
②倒排索引则相反,它是由文档内容来映射文档编号从而找到文档,而中文与英文不同,英文一个单词就是一个单词,单词与单词之间有空格隔开,中文则不同,没有规则的符号隔开,所以需要分词:例如:“谷歌”一词,在5个文档都存在,所以它对应的文档编号为:1,2,3,4,5
5.3.ES与Mysql、Mongo的比较
①在elasticSearch中,存储数据的行为称为索引( indexing )
②文档( document )归属于类型( type )
③类型( type )存在于索引( index )中
可以发现,elasticSearch与mongoDB有点相似,对比区别如下:
|
比较点 |
mysql |
mongoDB |
elastiSearch |
|
数据库 |
database |
database |
indexes |
|
表 |
table |
collection |
- |
|
行 |
row |
document |
document |
|
列 |
col |
field |
field |