elasticsearch原理,Elastisearch的实现原理是什么?主要应用场景是什么?

ElasticSearch(业界常称为ES)是一个全文搜索引擎,其特点为分布式,易扩展,实时文件存储与提取!

ES的底层使用Apache鼎鼎大名的Lucence开源框架实现,严格来说lucence只属于一个工具包,提供了简单的接口用于实现全文检索!

lucence有什么用呢?

想想我们使用天猫购物的时候,假设输入一个床,整个页面能显示木板床,水床,甚至有床垫,床单等购物信息出现,就是因为所有这些与床有关的信息录入时,以“床”这个词作为分词,建立索引,从而能得到各种与床有关的店铺,商品等等!
elasticsearch原理,Elastisearch的实现原理是什么?主要应用场景是什么?

如果用mysql,怎么实现呢,一大段商品信息描述,使用like'%床%'来查询,本来就不走索引,字段还很大,别说亿级别的数据了,几百万就能把一台mysql服务器搞死!

那么ES怎么做的呢?跟mysql的查找方式相反,mysql是从文档中提取关键字,而使用ES可以先提取出关键字(使用特定的分词器),然后关键字出现的位置,建立倒排索引,明确的记录关键词所在的位置,举例截图如下:
elasticsearch原理,Elastisearch的实现原理是什么?主要应用场景是什么?

图中的箭头所示的一列数据叫做Posting List,就是存放关键字对应的位置;这样在查询羽毛球的时候,能迅速返回证件号1的数据,查年龄20的时候,能迅速返回证件号2,3对应的数据;

图中的Term就是Term Dictionary(字典),ES对字段Term Dictionary进行了排序,然后使用二分法查找数据,查找到的效率为O(logN),为了避免磁盘IO的低性能,ES可以把字典放在了内存中来提升查询性能,那么问题来了,如果是亿万级的数据,年龄还好,但是爱好可能也是亿万级别的量,这时候内存可能就要爆了,于是就有了Term Index,就是将Term Dictionary再进行一次索引,比如说羽毛球这个词,建立一个索引树,使用羽字就可以定位到羽字开头的所有Term Dictionary,然后在使用二分法查找到需要的关键词,这样就可以只把Term Index放入内存,从而提升整个ES系统的处理能力;
elasticsearch原理,Elastisearch的实现原理是什么?主要应用场景是什么?

上面就是ES大概的原理,当然远不止于此,作为大数据领域中文档处理的佼佼者,ES大量使用在日志记录与分析,全文检索,数据统计等等情景中!

以上是ES简单的原理说明,对于分词器选择,字典树压缩,如何使用等更多的东西没有描述,以后找机会会详细分享一次,请关注。。。

elasticsearch原理,Elastisearch的实现原理是什么?主要应用场景是什么?

如何使用Socket在客户端实现长连接?

长连接貌似是一个很高深莫测的知识,但是只要你做直播、IM、游戏、弹幕里面的任何一种,或者是你的app想要实时的接收某些消息,你就会要接触到长连接技术。本文主要教你如何在客户端如何使用Socket实现长连接。

Socket背景知识

要做长连接的话,是不能用http协议来做的,因为http协议已经是应用层协议了,并且http协议是无状态的,而我们要做长连接,肯定是需要在应用层封装自己的业务,所以就需要基于TCP协议来做,而基于TCP协议的话,就要用到Socket了。

Socket是java针对tcp层通信封装的一套网络方案

TCP协议我们知道,是基于ip(或者域名)和端口对指定机器进行的点对点访问,他的连接成功有两个条件,就是对方ip可以到达和端口是开放的

Socket能帮完成TCP三次握手,而应用层的头部信息需要自己去解析,也就是说,自己要制定好协议,并且要去解析byte

http也有长连接。在http1.0的时候,使用的是短连接,也就是说,每次请求一次数据,都要重新建立连接。但是从http1.1之后,我们看到头部会有一个

Connection:keep-alive

这个表示tcp连接建立之后不会马上销毁,而是保存一段时间,在这段时间内如果需要请求改网站的其他数据,都是使用这个连接来完成传输的。

Socket使用方式

Socket看上去不是很好用,因为他是基于java.io来实现的,你要直接跟InputStream和OutputStream打交道,也就是直接跟byte[]打交道,所以用起来并不是这么友好。

下面通过一个简单的例子,往一台服务器发01 00 00 00 00这一串字节,服务器也返回相同的字节流,上代码:

@Test

public void testSocket() throws Exception {

logger.debug("start");

Socket socket = new Socket();

socket.connect(address);

byte[] output = new byte[]{(byte) 1, (byte) 0, (byte) 0, (byte) 0, (byte) 0};

socket.getOutputStream().write(output);

byte[] input = new byte[64];

int readByte = socket.getInputStream().read(input);

logger.debug("readByte " + readByte);

for (int i = 0; i < readByte; i++) {

logger.debug("read [" + i + "]:" + input[i]);

}

socket.close();

}

输出:

11:40:40.326 [main] DEBUG com.roy.test.SocketTest - start

11:40:40.345 [main] DEBUG com.roy.test.SocketTest - readByte 5

11:40:40.345 [main] DEBUG com.roy.test.SocketTest - read 1

11:40:40.345 [main] DEBUG com.roy.test.SocketTest - read 0

11:40:40.345 [main] DEBUG com.roy.test.SocketTest - read 0

11:40:40.345 [main] DEBUG com.roy.test.SocketTest - read 0

11:40:40.345 [main] DEBUG com.roy.test.SocketTest - read 0

看出来写起来还是比较麻烦的,主要就是InputStream, OutputStream 和byte[]使用起来太不方便了。

SocketChannel blocking

Socket为了优化自己的封装和并发性能,推出了nio包下面的SocketChannel,这个相比于Socket的好处就是并发性能的提高和封装的优化了。

SocketChannel有两种方式——阻塞和非阻塞的,阻塞的用法和Socket差不多,都是在read和write的时候会阻塞线程,下面用一段代码来实现相同的功能。

@Test

public void testSocketChannelBlock() throws Exception {

final SocketChannel channel = SocketChannel.open(address);

ByteBuffer output = ByteBuffer.allocate(5);

output.put((byte) 1);

output.putInt(0);

output.flip();

channel.write(output);

logger.debug("write complete, start read");

ByteBuffer input = ByteBuffer.allocate(5);

int readByte = channel.read(input);

logger.debug("readByte " + readByte);

input.flip();

if (readByte == -1) {

logger.debug("readByte == -1, return!");

return;

}

for (int i = 0; i < readByte; i++) {

logger.debug("read [" + i + "]:" + input.get());

}

}

log 输出:

23:24:34.684 [main] DEBUG com.dz.test.SocketTest - write complete, start read

23:24:34.901 [main] DEBUG com.dz.test.SocketTest - readByte 5

23:24:34.901 [main] DEBUG com.dz.test.SocketTest - read [0]:1

23:24:34.901 [main] DEBUG com.dz.test.SocketTest - read [1]:0

23:24:34.901 [main] DEBUG com.dz.test.SocketTest - read [2]:0

23:24:34.901 [main] DEBUG com.dz.test.SocketTest - read [3]:0

23:24:34.901 [main] DEBUG com.dz.test.SocketTest - read [4]:0

从上面的。封装优化主要体现在ByteBuffer,IntBuffer这一系列类的封装——因为是网络相关的,所以这里用到的主要是ByteBuffer。

ByteBuffer和byte[]最大的区别,就是ByteBuffer可以很方便的读取int, long等数据类型,他提供了getInt(), getInt(int offset)这样的方法,这种方法主要用在识别头部数据部分,因为头部数据一般都是由多种数据类型组成,比方说表示数据格式的contentType:String,表示长度的length:int等等,这些就是getInt()这样的方法主要的应用场景,而byte[]如果要取int,String相对来说就要复杂一些了,这是java.nio相比于java.io优势的一点。

这里需要说明一个比较坑的点,就是ByteBuffer.flip()这个方法,这个方法的作用主要是重置索引,在write()之前和read()之后调用,否则会因为索引不对,导致你的数据写不进去,读不出来。

ByteBuffer是一个功能强大的类,因为本文主要是讲Socket和SocketChannel,所以在这里就不做过多描述。具体ByteBuffer的详细介绍,可以参考:Java NIO系列教程(三) Buffer

而nio相比于io最大的优势还是在于并发性能,因为nio里面的n代表的就是non-blocking的意思,上面那个读取数据的代码也相对老旧,一般我们如果要用SocketChannel,都是用non-blocking的方式来实现的,而如果要用non-blocking模式,首先要介绍的就是Selector。

Selector

我们知道,传统io是阻塞的,也就是说,一个线程只能处理一个io流,也就是一个Socket。有了Selector之后,一个线程就能处理多个SocketChannel。

Selector的原

深圳大数据培训机构有哪些?

深圳大数据培训机构有哪些? elasticsearch原理,Elastisearch的实现原理是什么?主要应用场景是什么?

我表弟在黑马程序员学的大数据,不过现在还没就业,😂

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 xxx@163.com 举报,一经查实,本站将立刻删除。

发表评论

登录后才能评论