0%

分析器

Lucene的分析器是由分词器、过滤器以及字符映射器组成的

分词器

分词器tokenizer用来将文本切分为词条,词条是携带各种额外信息的词项,这些信息包括:词项在原始文本中的位置,词项的长度。分词器工作的结果被称为词条流,之后会将这些词条一个一个的推送给过滤器处理

过滤器

过滤器filter用于处理词条流中的词条,过滤器可以一个接一个的被调用,Lucene中有很多过滤器,如小写过滤器、同义词过滤器等

字符映射器

字符映射器character mapper用于调用分词器之前的文本预处理操作

Lucene的评分公式

为了计算文档的得分,需要考虑以下因子

  • 文档权重 索引期间赋予某个文档的权重值
  • 字段权重 查询期间赋予某个字段的权重值
  • 协调因子 基于文档中词项个数的协调因子,一个文档命中了查询中的词项越多,得分越高
  • 逆文档频率 一个基于词项的因子,用来告诉评分公式该词项有多罕见。逆文档频率越高,词项就越罕见,评分公式为包含罕见词项的文档加权
  • 长度范数 每字段的基于词项个数的归一化因子,一个字段包含的词项数越多,该因子权重越低
  • 词频 一个基于词项的因子,用来表示一个词项在某个文档中出现了多少次,词频越高,文档得分越高
  • 查询范数 一个基于查询的归一化因子,等于查询中词项的权重平方和
阅读全文 »

性能调优

操作系统参数调优

  • 增大文件打开限制上限 ulimit命令设置
  • 增大网络连接上限 内核参数net.core.somaxconn
  • 关闭swap分区 调整/etc/sysctl.conf文件中的vm.swappiness
  • 设置合理的预读缓冲区大小 预读可以有效减少磁盘的寻道次数和应用程序的IO等待时间,使用blackdev来设置预读缓冲区的大小

Hadoop参数调优

  • 限制每个TaskTracker上并发的MapTask和ReduceTask数目

    mapred-site.xml中配置

    mapreduce.tasktracker.map.tasks.maximum和mapreduce.tasktracker.reduce.tasks.maximum

Hadoop RPC

Hadoop RPC主要分为四个部分,分别是序列化层、函数调用层、网络传输层和服务器端处理框架,实现机制为:

  • 序列化层:主要作用是将结构化对象转为字节流以便于通过网络进行传输或写入持久存储。
  • 函数调用层:主要作用是定位要调用的函数并执行该参数,采用了java反射机制和动态代理实现了函数调用
  • 网络传输层:描述了client和server之间消息传输的方式,基于TCP/IP的socket机制
  • 服务器端处理框架:服务器端处理框架可被抽象为网络IO模型,采用了基于Reactor模式的事件驱动IO模型

如何保证接口幂等

接口幂等是指多次发送同一个请求,保证操作执行一次

通过概念得知需要多次发送同一个请求,那么多次请求的原因有哪些

  • 多次点击提交按钮
  • 点击页面刷新
  • 使用浏览器后退按钮重复之前的操作,导致重复提交表单
  • 使用浏览器历史记录重复提交表单
  • 请求retry重试机制

针对上述情况如何解决呢?

  • 前端js提交按钮进行处理,防止重复点击
  • 使用重定向方式,使得提交表单后重定向到提交成功页面,避免用户刷新页面导致的重复提交,也可以消除浏览器前进后退导致的问题
  • session中生成一个唯一标识,请求时将唯一标识写入到表单的隐藏字段中,后端判断唯一标识与session中的是否一致,一致则说明是第一次请求,处理该请求后移除session中的标识;不相等则说明是重复请求,不进行处理
  • 使用数据库进行防止,insert时使用唯一索引,update时使用乐观锁version

Elasticsearch Java Api

elasticsearch有很多Java Api提供使用

TransportClient

使用最原始的TransportClient来进行操作

1
2
3
4
5
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>5.4.0</version>
</dependency>

创建TransportClient,后续操作都需要用到该对象

1
2
3
TransportClient client = new PreBuiltTransportClient(Settings.EMPTY)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getLocalHost(),
9300));
阅读全文 »

脑裂问题

什么是脑裂?就是同一集群中的不同节点对于集群状态有了不一样的理解,比如elasticsearch集群中有节点A(主节点),节点B(从节点),若由于网络问题两个节点之间的通信中断了,此时两个节点都认为对方已经挂了,节点A不进行任何操作,因为节点A本身就是主节点;但是节点B会将本身提升为主节点,此时就会导致elasticsearch有了两个主节点,发送到节点A上的索引请求不会将数据分配到节点B,同时发送到节点B的请求也不会将数据分配到节点A。这种情况下导致搜索请求命中哪个节点结果都不会相同

为了避免脑裂的发生,elasticsearch提供了一些配置

  • discovery.zen.minimum_master_nodes 表示决定主节点选择过程中最少需要有多少个master节点,默认是1,最好配置为N/2+1
  • discovery.zen.ping.timeout 节点间网络通信的等待时间,默认3s

Lucene的段

倒排索引是有一定格式的,而这个格式一旦写入时非常难以改变的,那么如何进行增量索引呢?Lucene使用段来解决这个问题。对于每一个已经生成的段,其倒排索引结构不会再改变,而增量添加的文档添加到新的段中,段之间在一定时刻进行合并,从而形成新的倒排索引结构

可视化工具Luke

Luke是Lucene的可视化GUI,方便进行开发和诊断,主要功能

  • 查看文档和分析字段内容
  • 搜索索引
  • 执行索引和维护
  • 测试自定义的Lucene分词器

下载地址 https://github.com/DmitryKey/luke/releases

跨域

何为跨域?

这就需要了解浏览器的同源策略,所谓同源是指 ‘协议+域名+端口’三者相同,而跨域就是非同源的请求

如何解决?

  • 通过代理来避免,如使用nginx在后端转发请求,来避免前端出现跨域

    在server块中增加

    1
    2
    3
    4
    5
    6
    7
    8
    # 允许跨域请求的域,*代表所有
    add_header 'Access-Control-Allow-Origin' *;
    # 允许带上cookie请求
    add_header 'Access-Control-Allow-Credentials' 'true';
    # 允许请求的方法 GET POST等
    add_header 'Access-Control-Allow-Methods' *;
    # 允许请求的header
    add_header 'Access-Control-Allow-Headers' *;
  • 使用jsonp

    浏览器的同源策略不包含<script>、<img>、<iframe>这几个标签,而jsonp就是利用<script>标签跨域特性来进行的跨域数据访问,其原理是与服务器端约定好一个函数名,服务端接收到请求后,将返回一段JavaScript,在这段JavaScript代码中调用约定好的回调函数,并且将数据作为参数进行传递,当网页接收到这段JavaScript后,就会执行回调函数,数据就成功传输到客户端了

    其缺点是只支持GET请求

  • 在web项目中配置过滤器或拦截器来解决跨域

    1
    2
    3
    4
    httpServletResponse.setHeader("Access-Control-Allow-Origin", origin);
    httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
    httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
    httpServletResponse.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");