Sensei是Linkin公司开发的一个开源分布式实时半结构化数据库,他主要支持以下功能(根据官网翻译):
全文检索
实时更新
faceted search
key-value查询
在高并发更新与查询性能高
支持与Hadoop集成
初步的调研了以下该项目,发现他其实主要是在全文索引的基础封装了Browse Query Language (BQL,类似SQL)的查询语法,个人感觉该项目的优势主要是在以下几点:
支持BQL语法
相对与lucene的语法跟容易让人理解,而且对熟悉SQL的开发人员更友好。
集群维护简单
新加节点只要设置好节点本身的配置,启动后进程会自动加入集群,不需要修改其他服务器的配置或中心的服务器列表配置
支持实时索引
内部通过ZOIE实现实时索引检索,ZOIE是Linkin公司开发的一个开源实时索引引擎,底层基于lucene的RamDirectory实现。
本文主要是对该项目的系统架构以及一些关键的流程(建索引、检索、扩容、错误恢复)进行介绍
SenseiDB系统的整体架构如下图(出自官方网站):
sensei系统主要由以下几部分组成:
Sensei Node
实际处理索引以及检索请求的地方,保存索引数据,内部分为几个模块:
Zoie System
通过zoie保存索引数据,提供实时索引服务。在一个服务器上可以同时保存多个分区的数据,每个分区对应一个ZoieSystem对象。
Data Provider
负责从Data Gateway获取数据并传给ZoieSystem建索引,在分发数据的时候会根据分区信息进行分发。
Broker
负责接受用户查询,并根据均衡策略以及负载均衡分发到不同Sensei Node上进行查询,并对分布在不同分区上的数据进行合并,然后格式化输出给用户。
ZooKeeper
用于维护服务器节点集群的列表等信息,便于各个服务器节点直接协作。其信息基本上不需要人为的修改,只需要配置好每个节点自己的配置(如节点编号、存储的分区列表等),节点启动后会自动修改ZooKeeper中的数据。因此Sensei的集群管理相当简单。
Data Gateway
负责提供sensei数据源的模块,目前支持以下几种数据源:
jms
通过topic订阅的方式让所有sensei node获取到数据,用于在线更新的模式,但是没法提供安全恢复的功能。
文件
从指定文件获取索引的数据,多用于新建索引时导入原始数据。
jdbc
实际上是以数据库实现的持久化消息队列,需要有一个数据库表,里面带有一个类似时间戳的属性,sensei node定时来获取上一个最后获取的版本之后的数据来建索引。
kafka
linkedin自己实现的一个消息队列,还没有调研过。
实际上,在sensei的实现中,broker和Sensei Node是在同一个进程中实现的,并没有物理上的分离。
跟大部分分布式应用一样,sensei提供的是根据均衡字段值的哈希均衡,它提供的是一层的hash映射,即部署系统的时候,就把整个系统划分为多个分区,一台服务器同时负载若干个分区的数据。
Data gateway获取到新索引数据。
每个Sensei Node都从Data gateway获取到所有新索引数据,并各自过滤出自己负责的数据进行处理,其他的直接丢弃,这样做可以让Data gateway不用关注分区的策略,在加节点的时候比较简单。
在处理索引数据的时候,Sensei Node为每个分区启动一个Zoie System,也就是说每个Sensei Node中对应每个分区有一个独立的索引
不同的Sensei Node负责的分区可以有相互重叠的部分,以此当做镜像服务器,镜像服务器也可以提供检索服务器以此提高负载能力。
用户检索请求可以发送到任意一个broker,每个broker都是等价的,可以提供相同的检索服务。
broker根据用户查询的均衡字段,按照负载均衡策略分发到不同的Sensei Node进行检索。
在分发检索请求到Sensei Node的时候,由于每个Sensei Node负责多个分区的数据,所以还需要在请求中指定需要检索的分区
对于全局搜索的情况broker会把多个sensei node的结果进行合并。
如果是Data gateway挂了,整个系统会停止新的索引,但是检索不受影响,只要Data gateway重启之后,各个Sensei Node就会继续获取新数据。
如果是Sensei Node错误,对于可以持久化的数据源,如文件、http、数据库等,Sensei Node重启之后,就会从最后处理的数据版本开始重新拉取数据建索引,自动完成恢复。但对于jms的非持久化的数据源,好像索引会丢失。
Sensei提供的均衡策略是一级映射的关系,所以其扩容只能限制在一个服务器中本负责的多个分区拆分成多个服务器的情况,对于一个服务器只有一个分区的情况,只能够建立镜像服务器降低系统负载。
由 于Sensei建索引是由Sensei Node主动向数据源拉取数据的,所以只要配置好新Sensei Node的分区信息,直接启动,新节点便自动从数据源抓取建索引的请求重建索引并加入集群,但是看代码分析,如果以jmq作为数据源,好像没法实现在线的 扩容,只能先停止往jmq发建索引请求(停止建索引),然后从把现有分区索引文件拷贝到新的节点,启动新服务器后再继续往jmq发建索引请求。
值得注意的一点是,在一开始划分分区的时候,如果划分的分区太多,会导致索引在物理上分成多块,对于个人搜索效率会比较高,但是会影响全局搜索的性能;如果划分的分区太少,则扩容受限。
网易云新用户大礼包:https://www.163yun.com/gift
本文来自网易实践者社区,经作者何卓斌授权发布。