Mishards:集群分片中间件

    Mishards 简单工作原理

    Mishards 负责将上游请求拆分,并路由到内部各细分子服务,最后将子服务结果汇总,返回给上游。

    Mishards 适合大数据规模下的搜索场景。那么,怎么判断数据规模的大小呢?这个问题没有标准答案,因为这取决于实际生产环境中使用的硬件资源。这里提供一个简单的判断数据规模的思路:

    1. 如果你不在意延迟,当数据规模大于单台服务器上硬盘的可用容量时,你可以认为这种场景具有大的数据规模。例如,每次批处理 5000 条查询请求,服务端计算时间已经大于数据从硬盘到内存的加载时间,此时将硬盘的可用容量作为判断数据规模的标准。
    2. 如果你在意延迟,当数据规模大于单台服务器上的可用内存时,你也可以认为这种场景具有大的数据规模。

    基于 Mishards 的集群方案

    structure

    主要构件

    • 服务发现:获取读写节点的服务地址。
    • 负载均衡器
    • Mishards 节点:无状态, 可扩容。
    • Milvus 写节点:单节点,不可扩容。为避免单点故障,需为该节点部署高可用 HA 方案。
    • Milvus 读节点:有状态,可扩容。
    • 共享存储服务:Milvus 读写节点通过共享存储服务共享数据,可选择 NAS 或 NFS。
    • 元数据服务:目前只支持 MySQL。生产环境下需要部署 MySQL 高可用方案。

    全局配置

    参数是否必填类型默认值说明
    BooleanTrue选择是否启用 Debug 工作模式。目前 Debug 模式只会影响日志级别。
    • True:启用 Debug 工作模式。
    • False:不启用 Debug 工作模式。
    TIMEZONEStringUTC时区
    SERVER_PORTInteger19530定义 Mishards 的服务端口。
    WOSERVERStringMilvus 写节点地址,参考格式:tcp://127.0.0.1:19530

    元数据

    元数据记录了底层数据的组织结构信息。在分布式系统中,Milvus 写节点是元数据唯一的生产者,而 Mishards 节点、Milvus 写节点和读节点都是元数据的消费者。目前版本的 Milvus 只支持 MySQL 和 SQLite 作为元数据的存储后端。

    在分布式系统中,元数据的存储后端只能是 MySQL。

    服务发现

    服务发现为 Mishards 提供所有 Milvus 读写节点的地址信息。Mishards 定义了相关的服务发现接口 IServiceRegistryProvider,并通过插件模式提供了扩展的可能性。目前默认提供了两种插件:KubernetesProvider 对应 Kubernetes 集群;StaticProvider 对应静态配置。你可以仿照这两种插件的实现,定制自己的服务发现插件。

    参数是否必填类型默认值说明
    DISCOVERY_STATIC_HOSTSList[]DISCOVERY_CLASS_NAMEstatic 时,定义服务地址列表。列表中的地址以逗号隔开,例如 192.168.1.188,192.168.1.190
    DISCOVERY_STATIC_PORTInteger19530DISCOVERY_CLASS_NAMEstatic 时,定义服务地址监听端口。
    DISCOVERY_PLUGIN_PATHString用户自定义服务发现插件的搜索路径,默认使用系统搜索路径。
    DISCOVERY_CLASS_NAMEStringstatic在插件搜索路径下,根据类名搜索类,并将其实例化。目前系统提供 statickubernetes 两种类,默认使用 static
    DISCOVERY_KUBERNETES_NAMESPACEStringDISCOVERY_CLASS_NAMEkubernetes 时,定义 Milvus 集群的 namespace。
    DISCOVERY_KUBERNETES_IN_CLUSTERBooleanFalseDISCOVERY_CLASS_NAMEkubernetes 时,选择服务发现是否在集群中运行。
    DISCOVERY_KUBERNETES_POLL_INTERVALInteger5DISCOVERY_CLASS_NAMEkubernetes 时,定义服务发现监听周期(单位:秒)。
    DISCOVERY_KUBERNETES_POD_PATTStringDISCOVERY_CLASS_NAMEkubernetes 时,匹配 Milvus Pod 名字的正则表达式。
    DISCOVERY_KUBERNETES_LABEL_SELECTORStringSD_PROVIDERkubernetes 时,匹配 Milvus Pod 的标签,例如:tier=ro-servers

    分布式系统错综复杂,请求往往会分发给内部多个服务调用。为了方便问题的定位,我们需要跟踪内部的服务调用链。系统的复杂性越高,一个可行的链路追踪系统带来的好处就越明显。我们选择了已进入 CNCF 的 OpenTracing 分布式追踪标准, 提供与平台和厂商无关的 API,便于开发人员实现链路跟踪系统。

    Mishards 定义了相关的链路追踪接口,并通过插件模式提供了扩展的可能性。目前默认提供了基于 Jaeger 的插件。

    查阅 Jaeger Doc 了解怎样集成 Jaeger。

    日志

    集群服务日志文件分布在不同的服务节点上,因此你在排查问题需要登录到相关服务器获取日志。建议使用 ELK 日志分析组件来协同分析多个日志文件、排查问题。

    参数是否必填类型默认值说明
    LOG_LEVELStringDEBUG日志记录级别:DEBUG < INFO < WARNING < ERROR
    LOG_PATHString/tmp/mishards日志文件的存储路径
    LOG_NAMEStringlogfile日志文件的名称

    路由

    Mishards 从服务发现中心获取 Milvus 读写节点的地址信息,通过元数据服务获取底层数据元信息。Mishards 的路由策略就是对于这些素材的一种消费。如图有 10 个数据段(s1, s2, s3, …, s10)。现在选择基于数据段名字的一致性哈希路由策略(FileNameHashRingBased),Mishards 会将涉及 s1、s4、s6、s9 数据段的请求路由到 Milvus 1 节点,将涉及 s2、s3、s5 数据段的请求路由到 Milvus 2 节点,将涉及 s7、s8、s10 数据段的请求路由到 Milvus 3 节点。

    Mishards 定义了路由策略相关的接口,并通过插件提供扩展。你可以仿照默认的一致性哈希路由插件,根据自己的业务特点定制个性化路由。

    router

    Mishards 简单示例

    启动示例

    前提条件

    • Python 版本 3.6 及以上

    启动 Milvus 和 Mishards 实例

    请按照以下步骤在单机上启动单个 Milvus 实例和 Mishards 服务:

    1. 将 Milvus 仓库复制到本地:

      1. $ cd milvus/shards
      2. $ pip install -r requirements.txt
    2. 启动 Milvus 服务:

      • 如果 Docker 版本低于 v19.03,运行如下命令:
      1. $ sudo docker run --runtime=nvidia --rm -d -p 19530:19530 -v /tmp/milvus/db:/var/lib/milvus/db milvusdb/milvus:1.0.0-gpu-d030521-1ea92e
      • 否则,运行如下命令:
    3. 更改目录权限:

      1. $ sudo chown -R $USER:$USER /tmp/milvus
    4. 配置 Mishards 环境变量:

      1. $ cp mishards/.env.example mishards/.env
    5. 启动 Mishards 服务:

      1. $ python mishards/main.py

    使用 docker-compose 启动示例

    all_in_one 使用 Docker 容器启动 2 个 Milvus 实例、1 个 Mishards 中间件实例和 1 个 Jaeger 链路追踪实例。

    1. 安装 。
    2. 将 Milvus 仓库复制到本地:

    3. 启动所有服务:

      1. $ make deploy
    4. 检查确认服务状态:

      1. $ make probe_deploy
      2. Pass ==> Pass: Connected
      3. Fail ==> Error: Fail connecting to server on 127.0.0.1:19530. Timeout

    若要查看服务踪迹,使用浏览器打开 Jaeger 页面

    jaegertraces

    若要清理所有服务,请使用如下命令:

    1. $ make clean_deploy
    • Kubernetes 版本 1.10 及以上
    • Helm 版本 2.12.0 及以上

    关于 Helm 的使用请参考 。

    安装流程

    1. 添加 Helm Chart 仓库:

      1. $ helm repo add stable https://kubernetes-charts.storage.googleapis.com
    2. 安装 Chart 依赖:

      1. $ git clone https://github.com/milvus-io/milvus-helm.git
      2. $ cd milvus-helm/charts/milvus
      3. $ helm dep update
    3. 部署 Mishards:

      1. $ helm install --set cluster.enabled=true --set persistence.enabled=true milvus-release .
    4. 检查部署状态:

    卸载 Mishards

      1. $ helm delete milvus-release

    从单机升级到 Mishards 集群

    支持从单机服务升级到 Mishards 集群。

    1. 部署单机 Milvus:

      1. $ helm install --set persistence.enabled=true milvus-release .
    2. 升级到 Mishards 集群:

      1. $ helm upgrade --set cluster.enabled=true --set persistence.enabled=true milvus-release .

    注意事项

    Mishards 依赖共享存储,因此 Kubernetes 集群中必须有可用的 PV(Persistent Volumes), 并且保证 PV 能够同时被多个 Pod 共同使用。这里通过 persistence.enabled 来开启 Persistent Volumes。

    1. 为了共享数据,PV 访问模式必须被设置为 ReadOnlyMany 或者 ReadWriteMany
    2. 选择文件存储系统:

    • 关于 PersistentVolume 的申请及管理,请参阅 。
    • 关于 PersistentVolume 的访问模式,请参阅 Access Modes

    你可以在 找到 Milvus-Helm 支持的所有参数。

    1. 配置有多个读节点和多个 Mishards 分片中间件的集群。

      我们通常配置多个节点来保证服务的可用性以及提高吞吐率。下面的例子部署的 Mishards 集群包括:2 个分片中间件、2 个读节点、1 个写节点。

      1. $ helm install
      2. --set cluster.enabled=true \
      3. --set persistence.enabled=true \
      4. --set mishards.replica=2 \
      5. --set readonly.replica=2 \
      6. milvus-release .

      这里通过 mishards.replicareadonly.replica 控制副本集数量,默认值为 1。

      Mishards 集群中的写节点暂时不支持扩展。

    2. 使用外部已配置好的 MySQL 集群作为元数据数据库。

      为了配合本地部署,有些情况需要支持外部的 MySQL。Milvus-Helm 内部的 MySQL 服务不保证高可用,但你可以通过外部的 MySQL 集群来提升可用性。下面的例子就是基于外部 MySQL 的部署。

      1. $ helm install
      2. --set cluster.enabled=true \
      3. --set persistence.enabled=true \
      4. --set mysql.enabled=false \
      5. --set externalMysql.enabled=true \
      6. --set externalMysql.ip=192.168.1.xx \
      7. --set externalMysql.port=3306 \
      8. --set externalMysql.user=root \
      9. --set externalMysql.password=root \
      10. --set externalMysql.database=milvus \
      11. milvus-release .

      若使用外部的 MySQL,则不再需要 Helm 内置的 MySQL 服务。这里通过 mysql.enabled 来关闭 Helm 内置的 MySQL 服务。

    3. 读写节点的 Milvus 分别使用不同的配置。

      为了更合理地使用资源,我们希望读节点和写节点拥有不一样的配置。下面的例子配置了一个拥有 16 GB 内存的读节点和 8 GB 内存的写节点。

      • 更多 Milvus 配置参数,请参阅 Milvus 服务端配置
      • 更多 Milvus-Helm 配置参数,请参阅 。
    4. 配置 GPU 资源。

      1. $ helm install
      2. --set cluster.enabled=true \
      3. --set persistence.enabled=true \
      4. --set gpu.enabled=true \
      5. milvus-release .

      Kubernetes 集群中必须有可访问的 GPU 资源。关于 Kubernetes 中的 GPU 资源管理及调度,请参阅 Schedule GPUs