ES在MySQL、PHP中的使用

ES简介
ES 为什么比 mysql 快
Mysql 只有 term dictionary 这一层,是以 b-tree 排序的方式存储在磁盘上的。检索一个 term 需要若干次的 random access 的磁盘操作。而 Lucene 在 term dictionary 的基础上添加了 term index 来加速检索,term index 以树的形式缓存在内存中。从 term index 查到对应的 term dictionary 的 block 位置之后,再去磁盘上找 term,大大减少了磁盘的 random access 次数。另外:term index 在内存中是以 FST(finite state transducers)的形式保存的,其特点是非常节省内存。Term dictionary 在磁盘上是以分 block 的方式保存的,一个 block 内部利用公共前缀压缩,比如都是 Ab 开头的单词就可以把 Ab 省去。这样 term dictionary 可以比 b-tree 更节约磁盘空间。
同步数据库
我们采取 MySQL 的数据存储,利用 MySQL 的事务特性维护数据一致性,使用 ElasticSearch 进行数据汇集和查询,此时 es 与数据库的同步方案就尤为重要。
流程
首先添加商品入数据库,添加商品成功后,商品入 ES,若入 ES 失败,将失败的商品 ID 放入 redis 的缓存队列,且失败的商品 ID 入 log 文件(若出现 redis 挂掉,可从日志中取异常商品 ID 然后再入 ES),task 任务每秒刷新一下 redis 缓存队列,若是从缓存队列中取到商品 ID,则根据商品 ID 从数据库中获取商品数据然后入 ES。
使用
logstash-input-jdbc 插件同步数据库,安装,配置:创建一个 .conf 文件,配置了要同步的数据库和.sql 用于执行的 sql 语句,最后把一个 jdbc 驱动放到这个文件夹下,用来连接 mysql 数据库
【相关学习推荐:mysql教程】
可能遇到的问题
elasticsearch 数据重复以及增量同步
在默认配置下,tracking_column 这个值是 @timestamp,存在 elasticsearch 就是_id 值,是 logstash 存入 elasticsearch 的时间,这个值的主要作用类似 mysql 的主键,是唯一的,但是我们的时间戳其实是一直在变的,所以我们每次使用 select 语句查询的数据都会存入 elasticsearch 中,导致数据重复。
解决方法
在要查询的表中,找主键或者自增值的字段,将它设置为_id 的值,因为_id 值是唯一的,所以,当有重复的_id 的时候,数据就不会重复
数据同步频繁,影响 mysql 数据库性能
我们写入 jdbc.sql 文件的 mysql 语句是写死的,所以每次查询的数据库有很多是已经不需要去查询的,尤其是每次 select * from table; 的时候,对 mysql 数据库造成了非常大的压力
解决:
elasticsearch 存储容量不断上升
elasticsearch 为了数据安全,接收到数据后,先将数据写入内存和 translog,然后再建立索引写入到磁盘,这样即使突然断电,重启后,还可以通过 translog 恢复,不过这里由于我们每次查询都有很多重复的数据,而这些重复的数据又没有写入到 elasticsearch 的索引中,所以就囤积了下来,导致 elasticsearch 容量就不断上升
解决:
查询官网说会定期 refresh,会自动清理掉老的日志,因此可不做处理
增量同步和 mysql 范围查询导致 mysql 数据库有修改时无法同步到以前的数据。
解决了 mysql 每次都小范围查询,解决了数据库压力的问题,不过却导致无法同步老数据的修改问题
解决:
可根据业务状态来做,如果你数据库是修改频繁类型,那只能做全量更新了,但是高频率大范围扫描数据库来做的索引还不如不做索引了 (因为建立索引也是有成本的),我们做索引主要是针对一些数据量大,不常修改,很消耗数据库性能的情况。我这里是数据修改较少,而且修改也一般是近期数据,因为同步时,我在 mysql 范围上面稍微调整一下
php 使用 ES
php composer 安装 composer require elasticsearch/elasticsearch引入 es 文件 autoload.php 文件,设置 IP 地址创建 index,index 对应关系型数据(以下简称 MySQL)里面的数据库,而不是对应 MySQL 里面的索引有了数据库还不行,还需要建立表,ES 也是一样的,ES 中的 type 对应 MySQL 里面的表。type 不是单独定义的,而是和字段一起定义,字段定义在 body 中;当然可以在 body 字段中也能使用 ik 分词;使用 EsClient->search () 实现搜索;同义词和近义词的使用
【相关学习推荐:php编程(视频)】
配置分词器:配置 IK
下载 es 的 ik 版本包在 es 目录下的 plugins 在创建 ik 目录,把下载 ik 的 zip 包所有文件解压进去。进去 es 的 config 目录,编辑 elasticsearch.yml,在空白地方加上 index.analysis.analyzer.default.type : “ik” 即可。拼音分词器配置:使用已经编译好的:elasticsearch-analysis-pinyin-1.3.0在 elasticsearch 的 plugins 目录下,新建 analysis-pinyin 文件夹,解压压缩包,将里面的 jar 包放到 analysis-pinyin 文件夹。在 elasticsearch.yml 里面配置拼音分词器的过滤器
同义词分词器配置
在 elasticsearch.yml 里面配置好同义词分词器的过滤器配置同义词词库,在 elasticsearch 的 config 目录下新建 sysnonym.txt。配置 ik+pinying + 同义词的分词器,主要有分词器的名称,类型,分割词元的组件,对分割的次元做处理:这里使用的是拼音和同义词
ES 关键字高亮显示
ES 通过在查询的时候可以在查询之后的字段数据加上 html 标签字段,使文档在在 web 界面上显示的时候是由颜色或者字体格式的,是在 highlight 修饰高亮字段, 这个部分包含了 name 属性匹配的文本片段,并以 HTML 标签 封装
ES 查询分页
Elasticsearch 中数据都存储在分片中,当执行搜索时每个分片独立搜索后,数据再经过整合返回。
一般查询流程为
1) 客户端请求发给某个节点2) 节点转发给个个分片,查询每个分片上的前 10 条3) 结果返回给节点,整合数据,提取前 10 条4) 返回给请求客户端当我们查询第 10 条到第 20 条的数据时,有两种方式,包括深度分页 (from-size) 和快照分页 (scroll);深度分页 (from-size)
from 定义了目标数据的偏移值,size 定义当前返回的事件数目。默认 from 为 0,size 为 10,也就是说所有的查询默认仅仅返回前 10 条数据。查询前 20 条数据,然后截断前 10 条,只返回 10-20 的数据。浪费了前 10 条的查询。越往后的分页,执行的效率越低。分页的偏移值越大,执行分页查询时间就会越长
快照分页 (scroll)
- 调用: index/type/_search?pretty&scroll=2m,返回一个 scroll 值
- 直接用 scroll_id 进行查询。
- 清除 scroll,我们在设置开启 scroll 时,设置了一个 scroll 的存活时间,但是如果能够在使用完顺手关闭,可以提早释放资源,降低 ES 的负担
想了解更多编程学习,敬请关注php培训栏目!
以上就是ES在MySQL、PHP中的使用的详细内容,更多内容请关注技术你好其它相关文章!
1.资讯内容不构成投资建议,投资者应独立决策并自行承担风险
2.本文版权归属原作所有,仅代表作者本人观点,不代表本站的观点或立场