乐趣区

十二赞的商品搜索实现

其实要说很惭愧,虽然我是搜索出身人士,但是十二赞的搜索功能其实在目前是做得非常弱鸡的。不过还是介绍一下这个弱鸡的系统。
十二赞的搜索是基于 elasticsearch 的。因为业务量较小,所以,到目前为止,还没有用上 elasticsearch 强大可怕的集群功能。之所以觉得可以拿出来分享一下,是因为这个文案的投入是比较小的,效果尚可接受。
对于在小程序上开店的商家来说,一般商品数不多,很少于超过 200 的,所以在召加回率和精度上,我们只需要满足召回率就行了。即便搜索结果不够精准,因为商品少,用户一眼扫一下也能找到他想要的商品,搜索只是帮他从原有的上百个商品中把范围缩小到十分之一,就已经很有效了。
另外,也是因为团队小,我们的方案也特别注重精简,能不自己去写代码实现的,就不自己去写代码实现。
好了,上方案。
我们的商品数据是存在 MySQL 数据库中的,就用的阿里云的 RDS。我们运行了一个 go-mysql-elasticsearch, 这个程序启动时会运行一次 mysql_dump, 把数据导出进入 elasticsearch, 然后接下来就会作为 MySQL 的一个 slave, 不断地读取 MySQL 的 binlog,同步进 elastichsearch。跟我们其他的服务一样,我们把这个 elasticsearch 和 go-mysql-elasticsearch 也封装进了一个 docker 之中,只对外暴露 9200 端口来提供服务。
我们之前的 ppt 介绍过,十二赞的各种内部业务都已经微服务化,这个 elasticsearch 的服务,也不例外,它工作在 es-sec.z.12zan.net:3000 上,后端的实例可以有多个 es 的实例,通过 http 接口来请求 elastichsearch 的 http 接口时,网关 server 会自动定向到负载最低的 elasticsearch 实例来提供服务。
这个方案运行不久,我们就发现一个问题,当我们的 MySQL 数据库的商品表新增了字段时,所有的后续的数据更新都无法同步的 elasticsearch 中去了。因为 MySQL 表的字段比 elasticsearch 中的字段多了(字段减少啊变更什么的都会导致这个问题)。
谢天谢地,因为 Docker 化,我们可以轻而易举地解决这个问题。我们的方案,当 MySQL 的数据表 schema 变化时,老的 elasticsearch 实例不变,继续提供服务,但是有缺陷,因为新增的数据没有同步进来;同时,我们新启一个 Docker 实例,这个实例启动约 1 分钟之后就同步进来了所有的商品数据,这时是两个 elasticsearch 的实例都在 es-sec.z.12zan.net:3000 上对外提供 http 接口服务,其中一个的数据是老的,一个实例的数据是全的。这时候我们关掉老的 Docker 上的实例就好了,就实现了索引的切换。用户可能会感受到新商品没有马上在搜索结果里体现,感觉搜索里的商品更新有延迟,但是基本上发现这个延迟的概率很小。
其实,淘宝的搜索的索引切换也有这么一个过程,不过要复杂的多,每天夜里要生成一个全量的索引,切换掉前一天的索引;然后另外有一个实时的搜索引擎,数据全放在内存里,只同步当天的数据变更,对外提供服务的接口将两份数据合并。【原文链接】

退出移动版