#研发解决方案介绍#基于ES的搜索+筛选+排序解决方案
本文档适用人员:研发和运维
- 曾经的基于MongoDB的筛选+排序解决方案
- MongoDB方案的缺陷
- 看中了搜索引擎的facet特性
- 看中了ES的简洁
- 看中了ES的天生分布式设计
- 窝窝的ES方案
- ES的几次事故和教训
- ES自身存在的问题
|
|
由于频道页流量小于首页,尤其是用户很少点击到的深度筛选条件组合查询,所以下图中的所有枚举项商品数量都容易缓存失效或缓存挤出:
![]() 图2 筛选越来越复杂,标题数字却要保持准确性
一旦缓存失效后,但凡我从上图的“20元以下”点击切换到“51-80元”或做更深层次筛选,那么程序就要针对上面所有组合条件对 MongoDB 商品记录逐一做 count 计算。
虽然每一个 count 计算都很快不属于慢查询,但也架不住多啊,尤其是配上区县和商圈等动辄6、7层深的筛选组合,点击一次轻易就涉及成百次的 count 计算,代价还是很大的。
由于在商城模式下,不同频道很可能不断增加新筛选条件,导致筛选组合越来越复杂,最终可能要求我们从基于 NoSQL 的排序和筛选方案,尽快转变为基于搜索引擎的排序和筛选方案。
|
|
介绍分面
分面是指事物的多维度属性。例如一本书包含主题、作者、年代等分面。而分面搜索是指通过事物的这些属性不断筛选、过滤搜索结果的方法。可以将分面搜索看成搜索和浏览的结合。
灵活使用分面 有时用户并不明确自己的目的,因此提供宽松的筛选方式更符合这部分用户的预期。Bing 的旅行搜索中选择航班时,用户可以通过滑块来选择某个时间段起飞的航班。 |
- Field Facet:如果需要对多个字段进行Facet查询,那么将 facet.field 参数声明多次,Facet字段必须被索引;
- Date Facet:时间字段的取值有无限性,用户往往关心的不是某个时间点而是某个时间段内的查询统计结果,譬如按月份查;
- Facet Query:利用类似于filter query的语法提供了更为灵活的Facet,譬如根据价格字段查询时,可设定不同价格区间;

商品维度是我们主要的查询维度,其业务复杂度也比较高。针对网站查询特性,我们的商品主索引方案为:每个城市建立一个 index,所以一共有400多个 index,每个城市仅有1个主 shard(不分片)。这样做的好处是以后我们根据热点城市和非热点城市,可以将各个 index 手工分配到不同的 node 上,可以做很多优化。
其结构为:

图7 goodsinfo
为了减少索引量和功能拆分,减少商品索引的内存占用,所以我们把全文检索单独建为一个索引。
每个城市索引或者商品索引按频道分为几个type,如下图所示。

图9 type
商品频道映射到es的type是很容易理解的,因为每个频道的模型不同:有的频道特有“用餐人数”属性,有的频道特有“出发城市”和“目的地城市”属性 所以每个频道对应一个es的type,每个type绑定一种特定的mapping(这个mapping里面可以指定该频道各自的特殊属性如何储存到ES)。
ES 会保证所有 shard 的主副本不在同一个 node 上面,但我们是 ES 服务器集群,每台服务器上有多个 node,一个 shard 的主副本不在同一个节点还是不够的,我们还需要一个 shard 的主副本不在同一台服务器,甚至在多台物理机的情况下保证要保证不在同一个机架上,才可以保证系统的高可用性。
所以ES提供了一个配置:cluster.routing.allocation.awareness.attributes: rack_id。
这个属性保证了主副 shard 会分配到名称不同的 rack_id 上面。
当我们停止一个节点时,如停止 174_node_2,则 ES 会自动重新平衡数据,如下图所示:
图13 重新分布
即使一台物理机完全 down 掉,我们可以看到其他物理机上的数据是完整的,ES 依然可以保证服务正常。

查看其内存使用状况发现,ES 各个节点的 JVM perm 区均处于满或者将要满的状态,如下图所示:
图15 当时perm的容量
注1:jstat -gc <pid>命令返回结果集中,上图红色方框中字段的含义为:
PC Current permanent space capacity (KB). 当前perm的容量 ;
PU Permanent space utilization (KB). perm的使用。
大家可以看到图1中的PU值基本等于PC值了。
由于 ES 各个节点的 perm 区接近饱和状态,所以造成了服务器负载升高,GC 频繁,并进一步造成 ES 集群出现了类似于“脑裂”的状态。
- 引入新技术,还是要谨慎,毕竟如果真是 mevl 脚本引起的问题,其实线下做压力测试就能提前发现。
- 加强ES的监控。
- 虽然现在回过头来看,如果在第一时间重启所有 nodes,损失应该是最小的——但是王超认为当时采用的保守策略依然是有意义的,因为在弄清楚问题原因之前,直接重启 nodes 有可能反而造成更大的数据破坏。
Elastic Search 在窝窝运行几年来基本稳定,可靠性和可用性也比较高,但是也暴露了一些问题:
- ES 的更新效率,作为基于 lucene 的分布式中间件,受限于底层数据结构,所以其更新索引的效率较低,lucene 一直在优化;
- ES 的可靠性的前提是保证其集群的整体稳定性,但我们遇到的情况,往往是当某个节点性能不佳的情况下,可能会拖累与其同服务器上的所有节点,从而造成整个集群的不稳定。
- 其实解决这个问题不难,两种方法:
- 增加服务器,让节点尽可能地散开;
- 当某个节点出现问题的时候,需要我们及早发现处理,不至于拖累整个集群。其实监控一个节点是否正常的方法不难,ES 是基于 JVM 的服务,它出现问题,往往和 GC、和内存有关,所以只要监控其内存达到某个上限就报警即可;
- 没有一个好的客户端可视化集群管理工具,官方或者主流的可视化管理工具,基本都是基于 ES 插件的,不符合我们的要求,所以需要一款可用的客户端可视化集群管理工具;
- ES 的升级问题,由于 ES 是一个快速发展的中间件系统,每一次新版本的更新,更改较大,甚至导致我们无法兼容老版本,所以 ES 升级问题是个不小的问题,再加上我们数据量较大,迁移也比较困难。
——END——
窝窝的解决方案介绍列表:
#研发解决方案#基于StatsD+Graphite的智能监控解决方案
es术语介绍:
cluster:
代表一个集群,集群中有多个节点,其中有一个为主节点。这个主节点是可以通过选举产生的。注意,主从节点是对于集群内部来说的。es的一个概念就是去中心化,字面上理解就是无中心节点,这是对于集群外部来说的,因为从外部来看es集群,在逻辑上是个整体,你与任何一个节点的通信和与整个es集群通信是等价的。
shards
代表索引分片。es可以把一个完整的索引分成多个分片,这样的好处是可以把一个大的索引拆分成多个,分布到不同的节点上。构成分布式搜索。分片的数量只能在索引创建前指定,并且索引创建后不能更改。
replicas
代表索引副本,es可以设置多个索引的副本。副本的作用,一是提高系统的容错性,当某个节点的某个分片损坏或丢失时可以从副本中恢复,二是提高es的查询效率,es会自动对搜索请求进行负载均衡。
recovery
代表数据恢复或叫数据重新分布,es在有节点加入或退出时会根据机器的负载对索引分片进行重新分配,挂掉的节点重新启动时也会进行数据恢复。
river
代表es的一个数据源,也是其他存储方式(如:数据库)同步数据到es的一个方法。它是以插件方式存在的一个es服务,通过读取river中的数据并把它索引到es中,官方的river有couchDB的,RabbitMQ的,Twitter的,Wikipedia的。
gateway
代表es索引快照的存储方式。es默认是先把索引存放到内存中,当内存满了时再持久化到本地硬盘。gateway对索引快照进行存储,当这个es集群关闭再重新启动时,就会从gateway中读取索引备份数据。es支持多种类型的gateway,有本地文件系统(默认),分布式文件系统,Hadoop的HDFS和amazon的s3云存储服务。
discovery.zen
代表es的自动发现节点机制。es是一个基于p2p的系统,它先通过广播寻找存在的节点,再通过多播协议来进行节点之间的通信,同时也支持点对点的交互。
Transport
代表es内部节点或集群与客户端的交互方式。默认内部是使用tcp协议进行交互,同时它支持http协议(json格式)、thrift、servlet、memcached、zeroMQ等的传输协议(通过插件方式集成)。

#研发解决方案介绍#基于ES的搜索+筛选+排序解决方案的更多相关文章
- #研发解决方案介绍#基于StatsD+Graphite的智能监控解决方案
郑昀 基于李丹和刘奎的文档 创建于2014/12/5 关键词:监控.dashboard.PHP.graphite.statsd.whisper.carbon.grafana.influxdb.Pyth ...
- #研发解决方案介绍#Tracing(鹰眼)
郑昀 最后更新于2014/11/12 关键词:GoogleDapper.分布式跟踪.鹰眼.Tracing.HBase.HDFS. 本文档适用人员:研发 分布式系统为什么需要 Tracing? ...
- #研发解决方案介绍#IdCenter(内部统一认证系统)
郑昀 基于朱传志的设计文档 最后更新于2014/11/13 关键词:LDAP.认证.权限分配.IdCenter. 本文档适用人员:研发 曾经一个IT内部系统配一套帐号体系和授权 线上生产环境里 ...
- #研发解决方案介绍#Recsys-Evaluate(推荐评测)
郑昀 基于刘金鑫文档 最后更新于2014/12/1 关键词:recsys.推荐评测.Evaluation of Recommender System.piwik.flume.kafka.storm.r ...
- #研发中间件介绍#异步消息可靠推送Notify
郑昀 基于朱传志的设计文档 最后更新于2014/11/11 关键词:异步消息.订阅者集群.可伸缩.Push模式.Pull模式 本文档适用人员:研发 电商系统为什么需要 NotifyServer? ...
- #研发中间件介绍#定时任务调度与管理JobCenter
郑昀 最后更新于2014/11/11 关键词:定时任务.调度.监控报警.Job.crontab.Java 本文档适用人员:研发员工 没有JobCenter时我们要面对的: 电商业务链条很长,业 ...
- LeetCode 81——搜索旋转排序数组 II
1. 题目 2. 解答 2.1. 方法一 基于 LeetCode 33--搜索旋转排序数组 中的方法二. 当 nums[mid] = nums[right] 时,比如 [1, 1, 2, 1, 1], ...
- 手淘架构组最新实践 | iOS基于静态库插桩的⼆进制重排启动优化 抖音研发实践:基于二进制文件重排的解决方案 APP启动速度提升超15% 编译期插桩
抖音研发实践:基于二进制文件重排的解决方案 APP启动速度提升超15% 原创 Leo 字节跳动技术团队 2019-08-09 https://mp.weixin.qq.com/s/Drmmx5JtjG ...
- 著名ERP厂商的SSO单点登录解决方案介绍一
SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.它包括可以将这次主要的登录映射到其他应用中用于同一个用户 ...
随机推荐
- 浅谈 php 采用curl 函数库获取网页 cookie 和 带着cookie去访问 网页的方法!!!!
由于近段时间帮朋友开发一个能够查询正方教务系统的微信公众平台号.有所收获.这里总结下个人经验. 开讲前,先吐槽一下新浪云服务器,一个程序里的 同一个函数 在PC测试可以正常运行,在它那里就会挂的 ...
- c++编译器对多态的实现原理总结
问题:定义一个空的类型,里面没有任何的成员变量或者成员函数,对这个类型进行 sizeof 运算,结果是? 结果是1,因为空类型的实例不包含任何信息,按道理 sizeof 计算之后结果是0,但是在声明任 ...
- 使用普通用户替代root来管理IEE
环境:RHEL 6.4 + IEE 4.0.6 需求:IEE数据库之前是使用root用户部署和管理的,现在安全加固,将数据库交给普通用户iee来管理. 一.当前环境 二.安全加固 1.创建iee用户 ...
- 对于SQL Server,我需要多少内存
经常被问到的一个问题:对于SQL Server,我需要多少内存?这个问题还是有同样的典型的“看情况而定”答案.在今天的文章里,我们来详细看下“看情况而定的”的不同方面. 全新SQL Server安装 ...
- .Net语言 APP开发平台——Smobiler学习日志:实现手机上常见的ListMenuView
最前面的话:Smobiler是一个在VS环境中使用.Net语言来开发APP的开发平台,也许比Xamarin更方便 一.目标样式 我们要实现上图中的效果,需要如下的操作: 1.从工具栏上的"S ...
- Jsonp跨域访问
很早之前看过好几篇跨域访问的文章,然后做项目的时候基本没有遇到跨域访问的问题.不过该来的还是会来,前些天终于让我遇到了.于是重温了一下原理这些,再进行实战.于是现在也敢通过实战后的一些理解来和大家分享 ...
- 使用NPOI组件完成的Excel导出导入(附源代码,测试通过)
最近遇到一个Excel导入导出的问题,要支持winform和webform,这里我是一个认真严谨的coder,所以决定把这个记录下来!和大家一起分享一下!如果需要的同学可以下载哦! 对于NPOI这个组 ...
- C标准头文件<stdlib.h>
是个大杂烩,里面声明了从动态内存分配到常用算法等各种函数和宏 #数据类型 **size_t** **wchar_t** **div_t**是一个结构体类型,也是div()返回的类型 **ldiv_t* ...
- P2P核心业务体系
看似一个简单的充值.提现按钮,背后可是巨多的逻辑和业务处理.
- spring入门(六)【springMVC中各数据源配置】
在使用spring进行javaWeb开发的过程中,需要和数据库进行数据交换,为此要经常获取数据库连接,使用JDBC的方式获取数据库连接,使用完毕之后再释放连接,这种过程对系统资源的消耗无疑是很大的,这 ...


