背景
先从“赞”搜索的历史开始吧,概括总结一下,个人觉得主要分三个阶段:
1. 主业务阶段
-
这个阶段做了很多传统上的搜索业务,分销市场/买家版等等,主要是提升搜索的准确率和召回率,强化结果排名,最终提升市场gmv,是引擎(Elasticsearch)的使用者
2. 过渡阶段
-
随着SaaS服务商的定位,传统搜索入口这样的流量黑洞就成了历史,这段时间过得很挣扎,为了活下去尝试过很多种业务模式(也是埋坑最多的阶段),开始对外提供基础搜索服务,向引擎维护者转型
3. 主服务阶段
-
业务模式逐渐清晰,以对外提供基础搜索/数据存储服务为主,应用场景向存储型服务靠拢,成为引擎服务提供者
架构
“赞”搜索平台围绕重存储轻搜索的场景(可以参见前面写的一篇文章“轻搜索的困局和破局之道”)而设计,在平台前面加上“轻量”两字,并不是指体量小,而是说业务多样性。
为了保证性能,整个平台的设计尽量精简,不做任何多余的业务逻辑,简单画个架构图:
大致介绍下主要的组成部分:
1. es-console
-
一个索引的核心生命周期是:创建->配置->审核->上线->运行->下线,UI就是围绕索引核心生命周期而设计的,主要是为了简化操作,提升生产力,另外提供些可视化查询、测试工具包等增值工具
2. es-conf
-
存储索引核心生命周期需要的各项配置,另外新功能需要的配置项都作为附加表存储
-
index:索引配置(责任人、路由分片等)
-
field:字段配置(字段类型、分词等)
-
extra:附加配置(限速、缓存ttl、查询模板、开关等)
-
3. es-proxy
-
一条索引数据的核心生命周期是:创建->更新->读取->删除,proxy围绕这个生命周期而设计,数据是一个应用的核心,proxy也是搜索平台的核心组件,作为访问Es的中间层,负责数据路由和校验,必要时作为安全区保障引擎稳定工作
-
validator:索引/字段/路由校验
-
limiter:限速器
-
cache:缓存(远端/本地)
-
router:路由
-
planner:query分析
-
log tracer:日志记录,用于数据分析
-
adaptor:高低版本es适配器
-
monitor:监控数据采集
-
4. es-toolbox
-
做平台就是做生态,当能够方便的使用各项工具自助搭建服务的时候,一个系统才能叫做平台(还在努力中),目前只提供了查询拼接工具(query-builder)、大数据导出(datax-eswriter)几个产品
5. es
-
因为es不支持索引级别的资源隔离,为了保证核心链路业务的稳定,生产业务必须做物理隔离
-
沿用已久,高低版本同时存在,必须要做适配,降低业务迁移成本,也方便业务访问
目标
既然设计平台,就必须设定一个小目标,保证走在一条路上,这里简单介绍下我们对“赞”搜索的核心架构要素要求:
1. 性能
proxy用了dubbo框架来作为服务载体,比较偏应用层,其实对于一个偏重数据存储的服务来说有点太高层次了些,个人比较倾向的方式是在client中嵌入proxy逻辑代码,这样既能保留原生的es访问方法,又能减少用户感知,不过现有资源不足以采用这种方案,作为后期优化方向。
主要的几个手段:
-
流量的抖动很容易对服务性能产生影响,为了平滑抖动,削峰是个必要手段,Es就是通过队列来平滑增查改删操作,流量先入内存队列,不会对后端服务产生直接压力
-
如果流量持续不断的流入,即便是削峰也会有队列溢出,这时为了保证系统稳定,也有必要采取限流手段,我们采用了guava的ratelimiter实现
-
在大流量情况下,每次请求都访问真实数据很容易导致系统雪崩,缓存既能提高访问性能,又能降低存储压力,我们的缓存策略是优先分布式缓存保证数据一致性,自动检测热key降级为本地缓存,减轻后端压力
2. 扩展性
-
屏蔽细节,降低耦和,脱离了实际业务场景是设计不了好产品的,需要提炼业务的共性,但是耦合进业务的系统也不是一个好产品,业务代码的存在会使得后续的升级/改造难度几何级增大
-
真正的搜索应用使用的查询是比较复杂的,这时候用query-builder实现就不太方便了,反而是直接写query调试后用字符串拼接方便,但是这样会耦和到代码中,这时可以将查询提炼为模板,作为配置传入,采用占位符替换的方式修改其中的查询条件,不同的模板可以映射到不同的查询
3. 可用性
稳定压倒一切,一个时不时宕机的平台是不会有未来的,可用性是“赞”搜索设计首要考虑的,主要的几点:
-
软件层面加入了流量统计和异常统计监控接口/缓存命中率监控接口,可以直观反应系统运行压力;当然也有运维层面的进程/硬件监控
-
集群方式提供服务,通过dubbo服务发现实现服务高可用
4. 伸缩性
-
为了保证横向扩展能力,es-proxy是无状态的,所有的配置都在启动时初始化后保存在内存中,并且提供接口重载
-
通过dubbo服务权重控制来做负载均衡,http调用则通过nginx反向代理实现
结语
草稿打了好几遍,总是不合意,各位看官有什么意见和建议麻烦多提点提点~
欢迎大家关注跳跳爸的公众号: