Mar31

【原创】关于elasticsearch中拼音搜索的性能问题

Author: leeon  Click: 5508   Comments: 0 Category: 架构  Tag: elasticsearch,拼音

近日在elasticsearch按照网上的教程添加拼音支持后发行搜索性能衰减非常大,以前几百万的数据搜索关键字也只需要三四是毫秒,加入了多字段的拼音支持后搜索指定字段性能衰减了6-8倍。类似于网上的配置如下:

在索引分词器中配置如下:

[code="plain"]
index.refresh_interval: 1s
index:
analysis:
tokenizer:
my_pinyin:
type: "pinyin"
first_letter: "none"
padding_char: ""
analyzer:
ik_syno:
type: custom
tokenizer: ik_max_word
filter: [my_synonym_filter]
ik_syno_smart:
type: custom
tokenizer: ik_smart
filter: [my_synonym_filter]
pinyin_analyzer:
tokenizer: my_pinyin
filter: ["word_delimiter","my_ngram"]
py_analyzer:
tokenizer: my_pinyin
filter: ["standard"]
filter:
my_synonym_filter:
type: synonym
synonyms_path: analysis/synonym.txt
ignore_case: true
my_ngram:
type: "nGram"
min_gram: 2
max_gram: 5

[/code]

[code="plain"] {
"folks": {
"properties": {
"name": {
"type": "multi_field",
"fields": {
"name": {
"type": "string",
"store": "no",
"term_vector": "with_positions_offsets",
"analyzer": "pinyin_analyzer",
"boost": 10
},
"primitive": {
"type": "string",
"store": "yes",
"analyzer": "keyword"
}
}
}
}
}
}
[/code]

这种模式配置的字段映射会极大的降低搜索性能,如果想用拼音搜索关键字建议单独设立一个独立的字段来做,不要用multi_field复合字段的方式来配置,这样会大大降低在指定字段中搜索的性能,我猜测如果使用nGram方式来生成分词,会导致生成的token非常多,导致搜索匹配的数据太多导致查询太慢。

Mar22

【原创】elasticsearch使用analyze时出错问题

Author: leeon  Click: 5541   Comments: 1 Category: 架构  Tag: elasticsearch,analyze,analyzer

在使用elasticsearch-rtf 2.2.0版本时使用analyze命令测试配置的自定义分词器是否生效,结果运行后日志报错,我测试的url命令如下:

http://10.0.18.123:9200/_analyze?text=中文测试&analyzer=ik_syno

[code="plain"]
[ERROR][transport ] [Cassiopea] failed to handle exception for action [indices:admin/analyze[s]], handler [org.elasticsearch.action.support.single.shard.TransportSingleShar[email protected] ]
java.lang.NullPointerException
at org.elasticsearch.action.support.single.shard.TransportSingleShardAction$AsyncSingleAction.perform(TransportSingleShardAction.java:195)
at org.elasticsearch.action.support.single.shard.TransportSingleShardAction$AsyncSingleAction.access$700(TransportSingleShardAction.java:115)
at org.elasticsearch.action.support.single.shard.TransportSingleShardAction$AsyncSingleAction$1.handleException(TransportSingleShardAction.java:174)
at org.elasticsearch.transport.TransportService$DirectResponseChannel.processException(TransportService.java:821)
at org.elasticsearch.transport.TransportService$DirectResponseChannel.sendResponse(TransportService.java:799)
at org.elasticsearch.transport.TransportService$4.onFailure(TransportService.java:361)
at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:39)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
[/code]

查询google得知为最新的bug一枚,https://github.com/elastic/elasticsearch/pull/15447 ,做个记号。测试的时候需要在设置的索引上运行analyze来避免这个bug被触发。

http://10.0.18.123:9200/indexName/_analyze?text=中文测试&analyzer=ik_syno

Dec29

【原创】 APK增量升级架构设计分享

Author: leeon  Click: 8207   Comments: 2 Category: 架构  Tag: apk,android,增量更新,增量升级

       众所周知在国内应用发行领域增量升级技术做的最棒的当属应用宝,从apk的增量升级覆盖度和增量文件大小上都提供了近乎完美的实现方案,应用宝基本上可以涵盖用户90%以上的安卓软件更新提醒,可以说在国内其他大型的应用发行商店都无法做到应用宝这么广泛的增量升级体验,那么应用宝到底是如何实现这一架构的呢?

      应用宝采用腾讯自研的一套移动终端sdk开发框架和服务器通信框架来实现基础的网络通信功能,这样的设计方式完全区别于其他的安卓应用发型架构。豌豆荚,百度手机助手,91,以及360手机助手都没有实现二进制流的加密通信,都是json+http的方式来通信,而应用宝实现的是完整的HTTP二进制流的通信方式,这样我们是无法轻易获取应用宝的上下行通信数据,那么应用宝又是如何来实现应用的增量升级的呢?

     腾讯应用宝的数据除了提供给自身使用外,还提供给android版本的腾讯浏览器客户端使用。刚好腾讯的浏览器在对用户安装的软件做分析并上传服务器的整个过程中是没有做很严格的数据加密,可以抓包反向分析出腾讯是收集的用户安装的apk文件中的manifest.mf文件。大家都知道apk文件中manifest.mf文件代表了整个apk的文件指纹,他和加密数据一道构建了apk的完整签名,来保证软件的有效性。网上流传的各种增量升级方案都是依赖于完整apk的bsdiff解决方案,这种方案必须依赖于一个apk包的md5值得完全匹配,如果整个apk包有解压和再压缩的过程,那么狠容易导致整个包中的实际内容没有变化,但是重新压缩后的apk文件md5值变化,这就导致了bsdiff在合并的过程中失败。而腾讯的巧妙做法就避免了apk再次压缩的问题,完全精准的定位了一个apk包的版本特性,那就是收集每个apk保重的manifest.mf文件的md5值。

    大家都知道apk的应用包之所以很难做到增量升级是因为太多的渠道包,太多的同版本不同内部文件而导致差异化的包分发太广,服务器端无法完全收集到所有同版本的软件包来做增量文件的计算。笔者这里给出一个巧妙地方法,那就是在用户的终端上来收集manifest.mf的完整文件内容上传到服务器端,同时比对服务器端的最新版本APK包的manifest.mf文件中每一行的差异化数据,来判断用户客户端的旧版本和服务器端的新版本的差异文件,这样就可以获取到用户端的需要升级的差异化文件,从而保证了在服务器端不知道旧版本的情况下能智能分析输出差异包,应用宝之所以能支持几乎所有软件不同渠道的增量升级,我想他们的做法很有可能是在客户端的后台有定时的推送机制,就算没有支持到用户的增量升级,他们也可以做到异步的后台分析和计算,在用户下一次请求更新提醒接口时获取到增量升级的文件数据。

    那么又有人会问,为什么应用宝可以用一个增量升级文件来支持到非常多的渠道升级呢?他们的做法我想也就是同一个老版本不同渠道的manifest.mf文件的互相比对,来找出差异数据的合集,这样就保证了差异文件的最大共性化,再和新版本的文件进行比对,获取到最终的增量升级文件。

    服务器端计算增量升级文件的大致架构就是如此,其实并不难,主要就是如何收集用户的manifest.mf文件数据。又因为应用宝庞大的发行量,他们很容易收集到大量广泛的渠道apk包,因此大部分用户在收到升级提醒的时候都能做到增量文件的下载。

    那么客户端又如何支持到增量文件的安装呢?笔者如上所述的内容完全有别于网上一大堆bsdiff,xdelta的方案,因此必须实现自己的一套增量文件合并算法。笔者已经实现了一套高性能的apk合并算法,通过实际测试,合并性能和应用宝的增量升级的合并性能旗鼓相当,同时通过大规模的测试可以得出生成的增量升级文件的大小几乎和应用宝的增量升级文件一致。对于低端手机在增量升级安装过程中的性能和内存消耗和应用宝别无二致。其实这里的实现很简单,就是利用zip文件结构的特殊性,来重新组装增量升级文件和用户手机中的apk文件,利用java本省的nio特性来加速合并apk的过程。

    说了这么一大堆,还会觉得应用宝很难搞定了么?其实你也可以做出一款堪比应用宝的增量升级功能了。

Jan20

【原创】Sphinx中maxed out, dismissing client错误解决

Author: leeon  Click: 7922   Comments: 1 Category: 架构  Tag: sphinx,warning,maxed out

最近在使用sphinx的过程中一直有发现有搜索不到为空的情况,但是跟踪请求从query.log查询日志发现都有正常发送请求,并在日志中有记录返回数据量和耗时,但从searchd.log日志中发现有如下类似的信息出现:

[Mon Jan 20 09:54:53.503 2014] [30391] WARNING: maxed out, dismissing client

[Mon Jan 20 09:54:55.855 2014] [30391] WARNING: last message repeated 75 times

这类信息出现的时间通常是在索引定时更新的阶段,然后去sphinx官网论坛搜索了一番都说是将max_children 参数调大即可,国内各种sphinx的配置教程中基本都使用max_children=30 ,看来是一个大坑。原本以为这个参数是用在sphinx的prefork模式中来定义最大的子进程数,其实不然,这个参数也可以定义在线程模式下最大的并发处理线程数数量。

为了验证其参数意义做了一下测试,在高并发请求下更新索引,会导致searchd进程的响应处理时间增大,从而导致并发情况下线程数突增,当处理请求的线程数增长超过30个时,就会有抛弃请求的情况出现,这也就导致如上文所说的warning日志出现。笔者最后将max_children调大后再次做压力测试的同时更新索引,就再没有出现丢请求的问题,搜索为空的情况也没有再出现过了。

分类

标签

归档

最新评论

Abyss在00:04:28评论了
Linux中ramdisk,tmpfs,ramfs的介绍与性能测试
shallwe99在10:21:17评论了
【原创】如何在微信小程序开发中正确的使用vant ui组件
默一在09:04:53评论了
Berkeley DB 由浅入深【转自架构师杨建】
Memory在14:09:22评论了
【原创】最佳PHP框架选择(phalcon,yaf,laravel,thinkphp,yii)
leo在17:57:04评论了
shell中使用while循环ssh的注意事项

我看过的书

链接

其他

访问本站种子 本站平均热度:8823 c° 本站链接数:1 个 本站标签数:464 个 本站被评论次数:94 次