ElasticSearch 初学习总结 一

第一次了解到ElasticSearch是公司内部的报表查询的数据表过于庞大,引用缓存机制下载导致客户初次获取缓存信息下载时间过长,软件无法使用的情况而引用的。不采用直接查询数据库的原因简单说一下,是因为这个客户信息相关的表第一数据量太大了,遍历表查询很容易超时,也不符合业务逻辑,第二,相关表信息的引用处理真的太多了,存在嵌套查询和循环遍历的问题。从而决定了我们不能采用这种缓存和直接查询的方式处理。所以就探究一下ElasticSearch(以下简称为ES)的相关内容。

第一:什么是ES(ElasticSearch)?
1.1 Elasticsearch是一个基于Apache Lucene™的开源搜索引擎,是实时分布式搜索和分析引擎, Elastic 的意思是弹性的,search 就是搜索、查找的意思了,总结起来就是*动态搜索查找 *的意思。对于Apache字眼的我们应该很熟悉了。而至于Lucene这又是什么东西。简单来提一下Lucene,我们不必什么探究他的本质原理,不然先贤们的智慧结晶我们只是学习还不一定能够完成,更别说进行应用了(就是说别太钻牛角尖)。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。但是,Lucene只是一个库。想要使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。所以我们就直接拿来主义就好了,看看ES提出者神奇的逻辑处理如何将Lucene变的我们简单实用他的内核精神。

ES和Lucene关系阐述:Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。
ES的特点:
分布式的实时文件存储,每个字段都被索引并可被搜索
分布式的实时分析搜索引擎
可以扩展到上百台服务器,处理PB级结构化或非结构化数据
再加一个Lucene的核心特性,而且所有的这些功能被集成到一个服务里面,你的应用可以通过简单的RESTful API、各种语言的客户端甚至命令行与之交互。

有些小伙伴看到着可能会觉得我擦:怎么还涉及搜索引擎,那么复杂么?稍安勿躁,有道是说,大道至简啊。其实上手Elasticsearch非常容易。(或许也是相关大牛也考虑到我们的脑袋没有人家那么XX,)ES提供了许多合理的缺省值,并对初学者隐藏了复杂的搜索引擎理论。它安装即可使用,只需很少的学习既可在生产环境中使用。


感兴趣的小伙伴可以了解一下设计出ES的大牛和ES诞生的故事;Shay Banon


第二:安装使用
天上飞的理念总要有一个落地的实现,而一个落地的实现初步使用往往如同helloworld的一样简单。
ES安装和部署:
2.1 一点要求:
安装Elasticsearch唯一的要求是安装官方新版的Java,地址:www.java.com
2.2下载:
可以从 elasticsearch.org/download 下载最新版本的Elasticsearch。
在生产环境安装的时候可以使用:

curl -L -O http://download.elasticsearch.org/PATH/TO/VERSION.zip <1>
unzip elasticsearch-$VERSION.zip
cd  elasticsearch-$VERSION

从 elasticsearch.org/download 获得最新可用的版本号并填入URL中
还可以使用Debian或者RPM安装包,地址在这里:downloads page,或者也可以使用官方提供的 Puppet module 或者 Chef cookbook。
2.3监视工具 Marvel:
我们安装好了ES服务,我们都希望有一个东东帮我们记录和查看服务的处理,我们也不想用黑乎乎的控制台一致操作,习惯界面的我们也想要一个点点点就OK的好东东,那就是Marvel。
Marvel,在开发环境下免费使用。它包含了一个叫做Sense的交互式控制台,使用户方便的通过浏览器直接与Elasticsearch进行交互。安装Marvel不是必须的,但是它可以通过在你本地Elasticsearch集群中运行示例代码而增加与此书的互动性。
Marvel是一个插件,可在Elasticsearch目录中运行以下命令来下载和安装:

./bin/plugin -i elasticsearch/marvel/latest

如果你可能想要禁用监控,你可以通过以下命令关闭Marvel:

echo 'marvel.agent.enabled: false' >> ./config/elasticsearch.yml

2.4运行ES
执行以下命令可在前台启动:

./bin/elasticsearch

启动后,如果只有本地可以访问,尝试修改配置文件 elasticsearch.yml中network.host(注意配置文件格式不是以#开头的要空一格, :后要空一格) 为network.host: 0.0.0.0
如果想在后台以守护进程模式运行,添加-d参数。
打开另一个终端进行测试:

curl 'http://localhost:9200/?pretty'  //默认端口号都是9200

你能看到以下返回信息:

{
   "status": 200,
   "name": "Shrunken Bones",
   "version": {
      "number": "1.4.0",
      "lucene_version": "4.10"
   },
   "tagline": "You Know, for Search"
}
看到这个就说明我们ES启动成功并运行正常了

2.5 集群和节点
节点(node)是一个运行着的Elasticsearch实例。集群(cluster)是一组具有相同cluster.name的节点集合,他们协同工作,共享数据并提供故障转移和扩展功能,当然一个节点也可以组成一个集群。你最好找一个合适的名字来替代cluster.name的默认值,比如你自己的名字,这样可以防止一个新启动的节点加入到相同网络中的另一个同名的集群中。具体操作:可以通过修改config/目录下的elasticsearch.yml文件,然后重启ELasticsearch来做到这一点。
2.6查看Marvel和Sense
如果你安装了Marvel(作为管理和监控的工具),就可以在浏览器里通过以下地址访问它:

http://localhost:9200/_plugin/marvel/

你可以在Marvel中通过点击dashboards,在下拉菜单中访问Sense开发者控制台,或者直接访问以下地址:

http://localhost:9200/_plugin/marvel/sense/

以上操作我们只需要了解大致原理即可,因为一般情况下运维人员都可以帮助我们部署好对应的服务,到时我们直接用应用即可。如果有想要部署的小伙伴可以看下官网的具体操作。

与ElasticSearch交互[重点哦兄弟们]

所有程序语言都可以使用RESTful API,通过9200端口的与Elasticsearch进行通信,你可以使用你喜欢的WEB客户端,事实上,甚至可以通过curl命令与Elasticsearch通信。
Elasticsearch官方提供了多种程序语言的客户端——Groovy,Javascript, .NET,PHP,Perl,Python,以及 Ruby——还有很多由社区提供的客户端和插件,所有这些可以在文档中找到。

向Elasticsearch发出的请求的组成部分与其它普通的HTTP请求是一样的:

curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'

VERB  HTTP方法:GET, POST, PUT, HEAD, DELETE
PROTOCOL http或者https协议(只有在Elasticsearch前面有https代理的时候可用)
HOST Elasticsearch集群中的任何一个节点的主机名,如果是在本地的节点,那么就叫localhost
PORT Elasticsearch HTTP服务所在的端口,默认为9200
PATH API路径(例如_count将返回集群中文档的数量),PATH可以包含多个组件,例如_cluster/stats或者_nodes/stats/jvm
QUERY_STRING 一些可选的查询请求参数,例如?pretty参数将使请求返回更加美观易读的JSON数据
BODY 一个JSON格式的请求主体(如果请求需要的话)

举例说明,为了计算集群中的文档数量,我们可以这样做:

curl -XGET 'http://localhost:9200/_count?pretty' -d '
{
    "query": {
        "match_all": {}
    }
}

Elasticsearch返回一个类似200 OK的HTTP状态码和JSON格式的响应主体(除了HEAD请求)。上面的请求会得到如下的JSON格式的响应主体:

{
    "count" : 0,
    "_shards" : {
        "total" : 5,
        "successful" : 5,
        "failed" : 0
    }
}

当使用java进行交互时有所不同的,因为ES本来就是JAVA开发的么
Elasticsearch为Java用户提供了两种内置客户端:
节点客户端(node client):
节点客户端以无数据节点(none data node)身份加入集群,换言之,它自己不存储任何数据,但是它知道数据在集群中的具体位置,并且能够直接转发请求到对应的节点上。
传输客户端(Transport client):
这个更轻量的传输客户端能够发送请求到远程集群。它自己不加入集群,只是简单转发请求给集群中的节点。

两个Java客户端都通过9300端口与集群交互,使用Elasticsearch传输协议(Elasticsearch Transport Protocol)。集群中的节点之间也通过9300端口进行通信。如果此端口未开放,你的节点将不能组成集群。

TIP:Java客户端所在的Elasticsearch版本必须与集群中其他节点一致,否则,它们可能互相无法识别。
关于Java API的更多信息请查看:JAVA API

四 基本逻辑
【先总体来看一下ES和关系型数据库的不同】
Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。这种理解数据的方式与以往完全不同,这也是Elasticsearch能够执行复杂的全文搜索的原因之一。
先说Elasticsearch的文件存储,Elasticsearch是面向文档型数据库,一条数据在这里就是一个文档,用JSON作为文档序列化的格式,比如下面这条用户数据:

{
    "name":         "John Smith",
    "age":          42,
    "confirmed":    true,
    "join_date":    "2014-06-01",
    "home": {
        "lat":      51.5,
        "lon":      0.1
    },
    "accounts": [
        {
            "type": "facebook",
            "id":   "johnsmith"
        },
        {
            "type": "twitter",
            "id":   "johnsmith"
        }
    ]
}

用Mysql、SQL Server这样的数据库存储就会容易想到建立一张User表,有各种基本XXX的字段等,在Elasticsearch里这就是一个文档,当然这个文档会属于一个User的类型,各种各样的类型存在于一个索引当中。这里有一份简易的将Elasticsearch和关系型数据术语对照表:

关系数据库     ⇒ 数据库(DataBase)      ⇒ 表(Table)   ⇒ 行(Rows)        ⇒ 列(Columns)

Elasticsearch  ⇒ 索引(Index)         ⇒ 类型(type)  ⇒ 文档(Docments)  ⇒ 字段(Fields) 

Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices   -> Types  -> Documents -> Fields

一个 Elasticsearch 集群可以包含多个索引(数据库),也就是说其中包含了很多类型(表)。这些类型中包含了很多的文档(行),然后每个文档中又包含了很多的字段(列)。

Elasticsearch最关键的就是提供强大的索引能力了,InfoQ的这篇时间序列数据库的秘密 (2)——索引写的非常好,值的大家去拜读,另外Elasticsearch-基础介绍及索引原理分析这篇文章都有详细讲到,我这边就直接拿来部分文章内容和自己的理解来整理一下自己的心得。

依据上述的对照关系,我们接着来看具体的内容:
4.1 索引(Indexing)
通过上边和关系型数据库的映射,我们都应该知道了这个index索引与关系型数据库中的索引是不同的含义:

索引(名词) 如上文所述,一个索引(index)就像是传统关系数据库中的数据库,
					它是相关文档存储的地方,index的复数是indices 或indexes。
索引(动词) 「索引一个文档」表示把一个文档存储到索引(名词)里,以便它可以被检索或者查询。
					这很像SQL中的INSERT关键字,差别是,如果文档已经存在,新的文档将覆盖旧的文档。

倒排索引: 传统数据库为特定列增加一个索引,例如B-Tree索引来加速检索。Elasticsearch和Lucene使用一种叫做倒排索引(inverted index)的数据结构来达到相同目的。为何ES搜索速度远远优于传统关系型数据库原因就是倒排索引,相较于B_Tree索引的优势所在。时间序列数据库的秘密
默认情况下,文档中的所有字段都会被索引(拥有一个倒排索引),只有这样他们才是可被搜索的。

Elasticsearch索引的精髓:

一切设计都是为了提高搜索的性能

另一层意思:为了提高搜索的性能,难免会牺牲某些其他方面,比如插入/更新,否则其他数据库不用混了。前面看到往Elasticsearch里插入一条记录,其实就是直接PUT一个json的对象,这个对象有多个fields,比如上面例子中的name, age,confirmed, home,accounts, join_date,那么在插入这些数据到Elasticsearch的同时,Elasticsearch还默默的为这些字段建立索引–倒排索引,因为Elasticsearch最核心功能是搜索。
我们说Lucene的倒排索引相较于关系型数据库的B-Tree在搜索更有优势,那我们先要知道B-Tree是个什么东东[有知道的小伙伴可以略过或者进行斧正],他的原理是怎么处理的。

什么是b-tree索引
我们在学习数据结构的时候都应该接触过B-tree树,如果没有也应该听过二叉树的咯,B 树是为了磁盘或其它存储设备而设计的一种多叉平衡查找树。(相对于二叉,B树每个内结点有多个分支,即多叉)。
我们来介绍一下一颗m阶B-Tree的特性。
m阶的定义:一个节点能拥有的最大子节点数来表示这棵树的阶数。
for example:如果一个节点最多有n个key,那么这个节点最多就会有n+1个子节点,这棵树就叫做n+1(m=n+1)阶树。
包括以下5条特性:

1.每个结点x(假设为x)有如下属性:
-> x.n,表示当前存储在结点x中的关键字个数。
-> x.n的各个关键字本身:x.key1, x.key2, … 以非降序存放(升序),使得 x.key1 ≤ x.key2 ≤ …
-> x.leaf,是一个布尔值,如果x是叶子结点,则为TRUE, 如果x为内部结点,则为FALSE。

2.每个’内部结点x’还包含x.n+1个指向它的孩子的指针x.c1, x.c2, … 。 叶子结点没有孩子结点,所以他的ci属性没有定义。
-> key和指针互相间隔,节点两端是指针,所以节点中指针比key多一个。
-> 每个指针要么为null,要么指向另外一个节点。

3.关键字x.keyi对存储在各子树中的关键字进行分割:如果ki为任意一个存储在以x.ci为根的子树中的关键字,那么:
k1 ≤ x.key1 ≤ k2 x.key2 ≤ … ≤ x.keyx.n ≤ kx.n+1
难理解可以这么说:
如果某个指针在节点node最左边且不为null,则其指向节点的所有key小于(key1),其中(key1)为node的第一个key的值。

如果某个指针在节点node最右边且不为null,则其指向节点的所有key大于(keym),其中(keym)为node的最后一个key的值。

如果某个指针在节点node的左右相邻key分别是keyi和keyi+1且不为null,则其指向节点的所有key小于(keyi+1)且大于(keyi)。

4.每个叶子结点具有相同的深度,即树的高度h

5.每个结点所包含的的关键字个数有上界和下界。用一个被称作B树的最小度数的估计整数t(t ≥ 2)来表示这些界:
除了根结点以外的每个结点必须至少有t-1个关键字。因此,除了根节点以外的每个内部结点至少有t个孩子。(因为上面说了右x.n+1个指向它的孩子的指针)
如果树非空,根结点至少有一个关键字。
每个结点最多包含2t-1个关键字。因此,一个内部节点至多可有2t个孩子。当一个结点恰好有2t-1个关键字时,称该结点是满的(full)。

3阶B-tree示意图
在这里插入图片描述
拿中间一层最左边举例说明:

  1. x.n = 2 有俩个关键字
    分别为 x.key1 = 8 x.key2 = 12 且 8<12
    x.leaf = false为内部节点
  2. 含有3个指向它孩子的指针P1 P2 P3
  3. 关键字x.key1=8 它的左边指针P1 对 子树 3 5 分割 满足 3和5都小于8
    关键字x.key1=8 它的右边指针P2 对 子树 9 10 分割 满足 9和10都大于8(同为12的左指针)
    关键字x.key2=12 它的右边指针P3 对 子树 13 15 分割 满足 13和15都大于12

实际磁盘举例
在这里插入图片描述
来模拟下查找文件29 的过程:
(1) 根据根结点指针找到文件目录的根磁盘块1,将其中的信息导入内存。
【磁盘IO操作1次】
(2) 此时内存中有两个文件名17,35和三个存储其他磁盘页面地址的数据。根据算法我们发现17<29<35,因此我们找到指针p2。
(3) 根据p2指针,我们定位到磁盘块3,并将其中的信息导入内存。
【磁盘IO操作2次】
(4) 此时内存中有两个文件名26,30和三个存储其他磁盘页面地址的数据。根据算法我们发现26<29<30,因此我们找到指针p2。
(5) 根据p2指针,我们定位到磁盘块8,并将其中的信息导入内存。
【磁盘IO操作3次】
(6) 此时内存中有两个文件名28,29。根据算法我们查找到文件29,并定位了该文件内存的磁盘地址。


一颗m阶的B+树和m阶的B树的差异在于:

3阶B+树
1.非叶子结点的子树指针与关键字个数相同;
2.非叶子结点的子树指针P[i],指向关键字值属于[K[i], K[i+1])的子树(B-树是开区间)
3.为所有叶子结点增加一个链指针。图中Q是通过指针连在一起的。
4.所有关键字都在叶子结点出现。(5 8 9 || 10 15 18 || 20 26 …等等)叶子结点相当于是存储(关键字)数据的数据层;
5.B+树只有达到叶子结点才命中(B-树可以在非叶子结点命中)
6.所有的非终端结点可以看成是索引部分,结点中的关键字是有其孩子指向的子树中最大(或最小)关键字。比如第二层5 它的子树为5 8 9 (而B 树的非终节点也包含需要查找的有效信息)

B+树在MyISAM索引实现
叶节点的data域存放的是数据记录的地址
在这里插入图片描述
MyISAM的索引方式也叫做“非聚集”的,之所以这么称呼是为了与InnoDB的聚集索引区分。

B+树比B树更适合数据库索引
1、 B+树的磁盘读写代价更低:B+树的内部节点并没有指向关键字具体信息的指针,因此其内部节点相对B树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了。

2、B+树的查询效率更加稳定:由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

3、由于B+树的数据都存储在叶子结点中,分支结点均为索引,方便扫库,只需要扫一遍叶子结点即可,但是B树因为其分支结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫,所以B+树更加适合在区间查询的情况,所以通常B+树用于数据库索引。

B树的插入和删除之后有空在讲,先了解对应的传统数据库的索引建立,通过对比就可以知道ES为什么在大数据中引用如此之多的原因所在了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值