上手必读#

由于OpenMLDB是分布式系统,多种模式,客户端丰富,初次使用可能会有很多疑问,或者遇到一些运行、使用问题,本文从新手使用的角度,讲解如何进行诊断调试,需要帮助时如何提供有效信息给技术人员等等。

错误诊断#

在使用OpenMLDB的过程中,除了SQL语法错误,其他错误信息可能不够直观,但很可能与集群状态有关。所以,错误诊断需要先确认集群状态。在发现错误时,请先使用诊断工具的一键诊断功能。一键诊断可以输出全面直观的诊断报告,如果不能使用此工具,可以手动执行SHOW COMPONENTS;SHOW TABLE STATUS LIKE '%';提供部分信息。

报告将展示集群的组件、在线表等状态,也会提示用户如何修复,请按照报告内容进行操作,详情见一键inspect

openmldb_tool inspect [-c=0.0.0.0:2181/openmldb]

需要注意,由于离线存储只会在执行离线job时被读取,而离线job也不是一个持续的状态,所以,一键诊断只能展示TaskManager组件状态,不会诊断离线存储,也无法诊断离线job的执行错误,离线job诊断见离线SQL执行

如果诊断报告认为集群健康,但仍然无法解决问题,请提供错误和诊断报告给我们。

创建OpenMLDB与连接#

首先,我们建议不熟悉分布式多进程管理的新手使用docker创建OpenMLDB,方便快速上手。熟悉OpenMLDB各组件之后,再尝试分布式部署。

docker创建OpenMLDB见快速上手,请注意文档中有两个版本,单机版和集群版。请清楚自己要创建哪个版本,不要混合使用。

启动成功的标准是可以使用CLI连接上OpenMLDB服务端(即使用/work/openmldb/bin/openmldb连接OpenMLDB,单机或集群均可以通过CLI连接),并且执行show components;可以看到OpenMLDB服务端组件的运行情况。推荐使用诊断工具,执行status和inspect,可以得到更可靠的诊断结果。

如果CLI无法连接OpenMLDB,请先确认进程是否运行正常,可以通过ps f|grep bin/openmldb确认nameserver和tabletserver进程,集群版还需要通过ps f | grep zoo.cfg来确认zk服务,ps f | grep TaskManagerServer来确认taskmanager进程。

如果所有服务进程都运行中,但CLI连接服务端失败,请确认CLI运行的参数。如果仍有问题,请联系我们并提供CLI的错误信息。

See also

如果我们还需要OpenMLDB服务端的配置和日志,可以使用诊断工具获取,见下文

部署工具说明#

请确定你使用的是什么部署方式,通常我们只考虑两种部署方式,见安装部署,“一键部署”也被称为sbin部署方式。配置文件如何修改,日志文件在何处,都与部署方式联系紧密,所以必须准确。

  • sbin部署 sbin部署会经过deploy(拷贝安装包至各个节点),再启动组件。需要明确的是,部署节点就是执行sbin的节点,尽量不要在运维中更换目录。deploy到hosts中各个节点的目录中,这些节点的目录我们称为运行目录。

配置文件会在deploy阶段,从template文件生成,所以,如果你要修改某组件的配置,不要在节点上修改,需要在部署地点修改template文件。如果你不进行deploy操作,可以在节点运行目录上原地修改配置文件(非template),但deploy将覆盖修改,需要谨慎处理。

出现任何非预期的情况,以sbin部署的最终配置文件,即组件节点的运行目录中的配置文件为准。运行目录查看conf/hosts,例如,localhost:10921 /tmp/openmldb/tablet-1说明tablet1的运行目录是/tmp/openmldb/tablet-1localhost:7527目录为空说明该组件就运行在$OPENMLDB_HOME(如未指定,就是指部署目录)。如果你无法自行解决,提供最终配置文件给我们。

sbin日志文件地址,需要先查看hosts确认组件节点的运行目录,TaskManager日志通常在<dir>/taskmanager/bin/logs中,其他组件日志均在<dir>/logs中。如有特别配置,以配置项为准。

  • 手动部署 手动部署只要使用脚本bin/start.shconf/目录中的配置文件(非template结尾)。唯一需要注意的是,spark.home可以为空,那么会读取SPARK_HOME环境变量。如果你认为环境变量有问题,导致启动不了TaskManager,推荐写配置spark.home

手动部署的组件日志文件,以运行bin/start.sh的目录为准,TaskManager日志通常在<dir>/taskmanager/bin/logs中,其他组件日志均在<dir>/logs中。如有特别配置,以配置项为准。

运维#

  • 上文提到,inspect能帮我们检查集群状态,如果有问题,可使用recoverdata工具。但这是事后修复手段,通常情况下,我们应该通过正确的运维手段避免这类问题。需要上下线节点时,不要主动地kill全部Tablet再重启。请尽量用扩缩容的方式来操作,详情见扩缩容

    • 如果你认为已有数据不重要,更需要快速地上下线,那么可以直接重启节点。stop-all.shstart-all.sh脚本是给快速重建集群用的,可能会导致在线表数据恢复失败,不保证能修复

  • 各组件在长期服务中也可能出现网络抖动、慢节点等复杂问题,请开启监控。如果监控中服务端表现正常,可以怀疑是你的客户端或网络问题。如果监控中服务端就出现延迟高,qps低等情况,请向我们提供相关监控图。

理解存储#

OpenMLDB是在线离线存储计算分离的,所以,你需要明确自己导入数据或查询数据是处于在线模式还是离线模式。

离线存储在HDFS等地,如果你认为导入到离线存储的数据有缺漏,需要到存储地点进行进一步检查。

在线存储需要注意以下几点:

  • 在线存储是有TTL概念的,所以,如果你导入数据后检查发现数据少了,可能是数据因为过期被淘汰了。

  • 在线存储适合使用select count(*) from t1show table status来检查条数,请不要使用select * from t1来检查,可能有数据截断,这种查询只适合预览数据。

关于如何设计你的数据流入流出,可参考实时决策系统中 OpenMLDB 的常见架构整合方式

在线表#

在线表是存在内存中的数据,同时也会使用硬盘进行备份恢复。在线表的数据,可以通过select count(*) from t1来检查条数,或者使用show table status来查看表状态(可能有一定延迟,可以稍等再查)。

在线表是可以有多个索引的,通过desc <table>可以查看。写入一条数据时每个索引中都会写入一条,区别是各个索引的分类排序不同。但由于索引还有TTL淘汰机制,各个索引的数据量可能不一致。select count(*) from t1show table status的结果是第一个索引的数据量,它并不代表其他索引的数据量。SQL查询会使用哪一个索引,是由SQL Engine选择的最优索引,可以通过SQL物理计划来查看。

建表时,可以指定索引,也可以不指定,不指定时,会默认创建一个索引。如果是默认索引,它无ts列(用当前time作为排序列,我们称为time索引)将会永不淘汰数据,可以以它为标准检查数据量是否准确,但这样的索引会占用太多的内存,目前也不可以删除第一条索引(计划未来支持),可以通过NS Client修改TTL淘汰数据,减少它的内存占用。

time索引(无ts的索引)还会影响PutIfAbsent导入。如果你的数据导入可能中途失败,无其他方法进行删除或去重,想要使用PutIfAbsent来进行导入重试时,请参考PutIfAbsent说明对自己的数据进行评估,避免PutIfAbsent效率太差。

源数据#

LOAD DATA#

从文件导入数据到OpenMLDB,通常使用LOAD DATA命令,详情参考LOAD DATA INFILE。LOAD DATA可使用的数据源和数据格式,与OpenMLDB版本(单机/集群)、执行模式、导入模式(即LOAD DATA配置项load_mode)都有一定关系。集群版默认 load_mode 为cluster,也可设置为local;单机版默认 load_mode 为local,不支持cluster。所以我们分为三种情况讨论:

LOAD DATA类型

支持执行模式(导入目的地)

支持异步/同步

支持数据源

支持数据格式

集群版 load_mode=cluster

在线、离线

异步、同步

file(有条件限制,请参考具体文档)/hdfs/hive

csv/parquet(hive源不限制格式)

集群版 load_mode=local

在线

同步

客户端本地file

csv

单机版(only local)

在线

同步

客户端本地file

csv

当LOAD DATA的源数据为csv格式时,还需额外注意列类型为timestamp列的格式问题。timestamp格式可分为”int64”(以下称为int64型)和”yyyy-MM-dd’T’HH:mm:ss[.SSS][XXX]”(以下称为年月日型)。所以我们分为三种讨论:

LOAD DATA类型

支持int64

支持年月日

集群版 load_mode=cluster

集群版 load_mode=local

X

单机版(only local)

X

Hint

csv文件格式有诸多不便,更推荐使用parquet格式,需要OpenMLDB集群版并启动taskmanager组件。

OpenMLDB SQL 开发和调试#

OpenMLDB并不完全兼容标准SQL。所以,部分SQL执行会得不到预期结果。如果发现SQL执行不符合预期,请先查看下SQL是否满足功能边界

为了方便使用 OpenMLDB SQL 进行开发、调试、验证,我们强烈推荐使用社区工具 OpenMLDB SQL Emulator 来进行 SQL 模拟开发,可以节省大量的部署、编译、索引构建、任务运行等待时间,详见该项目 README https://github.com/vagetablechicken/OpenMLDBSQLEmulator

OpenMLDB SQL语法指南#

基于 OpenMLDB SQL 的特征计算,一般比较常使用WINDOW(包括WINDOW UNION),LAST JOIN 等子句来完成计算逻辑,它们能保证在任何模式下使用。可以跟随教程”基于 SQL 的特征开发”(上)(下)进行学习。

如果使用WHEREWITHHAVING等子句,需要注意限制条件。在每个子句的详细文档中都有具体的说明,比如HAVING子句在在线请求模式中不支持。翻阅OpenMLDB SQL的DQL目录,或使用搜索功能,可以快速找到子句的详细文档。

在不熟悉OpenMLDB SQL的情况下,我们建议从子句开始编写SQL,确保每个子句都能通过,再逐步组合成完整的SQL。

推荐使用OpenMLDB SQL Emulator进行SQL探索和验证,SQL验证完成后再去真实集群进行上线,可以避免浪费大量时间在索引构建、数据导入、任务等待等过程上。 Emulator 可以不依赖真实OpenMLDB集群,在一个交互式虚拟环境中,快速创建表、校验SQL、导出当前环境等等,详情参考该项目的 README 。使用 Emulator 不需要操作集群,也就不需要测试后清理集群,还可通过少量的数据进行SQL运行测试,比较适合SQL探索时期。

OpenMLDB SQL 语法错误提示#

当发现SQL编译报错时,需要查看错误信息。例如Syntax error: Expected XXX but got keyword YYY错误,它说明SQL不符合语法,通常是某些关键字写错了位置,或并没有这种写法。详情需要查询错误的子句文档,可注意子句的Syntax章节,它详细说明了每个部分的组成,请检查SQL是否符合要求。

比如,WINDOW子句WindowFrameClause (WindowAttribute)*部分,我们再拆解它就是WindowFrameUnits WindowFrameBounds [WindowFrameMaxSize] (WindowAttribute)*。那么,WindowFrameUnits WindowFrameBounds MAXSIZE 10 EXCLUDE CURRENT_TIME就是符合语法的,WindowFrameUnits WindowFrameBounds EXCLUDE CURRENT_TIME MAXSIZE 10就是不符合语法的,不能把WindowFrameMaxSize放到WindowFrameClause外面。

OpenMLDB SQL 计算正确性调试#

SQL编译通过以后,可以基于数据进行计算。如果计算结果不符合预期,请逐步检查:

  • SQL无论是一列还是多列计算结果不符合预期,建议都请选择其中一列进行调试。

  • 如果你的表数据较多,建议使用小数据量(几行,几十行的量级)来测试,也可以使用OpenMLDB SQL Emulator的运行toydb功能,构造case进行测试。

  • 该列是不是表示了自己想表达的意思,是否使用了不符合预期的函数,或者函数参数错误。

  • 该列如果是窗口聚合的结果,是不是WINDOW定义错误,导致窗口范围不对。参考推断窗口进行检查,使用小数据进行验证测试。

如果你仍然无法解决问题,可以提供 OpenMLDB SQL Emulator 的 yaml case 。如果在集群中进行的测试,请提供复现脚本

在线请求模式测试#

SQL上线,等价于DEPLOY <name> <SQL>成功。但DEPLOY操作是一个很“重”的操作,SQL如果可以上线,将会创建或修改索引并复制数据到新索引。所以,在SQL探索期使用DEPLOY测试SQL是否能上线,是比较浪费资源的,尤其是某些SQL可能需要多次修改才能上线,多次的DEPLOY可能产生很多无用的索引。在探索期间,可能还会修改表Schema,又需要删除和再创建。这些操作都是只能手动处理,比较繁琐。

如果你对OpenMLDB SQL较熟悉,一些场景下可以用“在线预览模式”进行测试,但“在线预览模式”不等于“在线请求模式”,不能保证一定可以上线。如果你对索引较为熟悉,可以通过EXPLAIN <SQL>来确认SQL是否可以上线,但EXPLAIN的检查较为严格,可能因为当前表没有匹配的索引,而判定SQL无法在“在线请求模式”中执行(因为无索引而无法保证实时性能,所以被拒绝)。

目前只有Java SDK可以使用validateSQLInRequest方法来检验,使用上稍麻烦。我们推荐使用 OpenMLDB SQL Emulator 来测试。在 Emulator 中,通过简单语法创建表,再使用valreq <SQL>可以判断是否能上线。

OpenMLDB SQL 执行#

OpenMLDB 所有命令均为 SQL,如果 SQL 执行失败或交互有问题(不知道命令是否执行成功),请先确认 SQL 书写是否有误,命令并未执行,还是命令进入了执行阶段。

例如,下面提示Syntax error的是SQL书写有误,请参考OpenMLDB SQL语法指南纠正错误。

127.0.0.1:7527/db> create table t1(c1 int;
Error: Syntax error: Expected ")" or "," but got ";" [at 1:23]
create table t1(c1 int;
                      ^

如果是命令进入执行阶段,但执行失败或交互有问题,需要明确以下几点:

  • OpenMLDB是单机还是集群?

  • 执行模式是什么?CLI运行命令时可以使用show variable获取,但注意单机版的执行模式没有意义

我们需要特别注意集群版的一些使用逻辑。

集群版离线 SQL 执行注意事项#

如果是集群离线命令,默认异步模式下,发送命令会得到job id的返回。可使用show job <id>来查询job执行情况。

离线job如果是异步SELECT(并不INTO保存结果),也不会将结果打印在客户端,而同步SELECT将会打印结果到控制台。可以通过show joblog <id>来获得结果,结果中包含stdout和stderr两部分,stdout为查询结果,stderr为job运行日志。如果发现job failed或者其他状态,不符合你的预期,请仔细查看job运行日志。

离线job日志中可能有一定的干扰日志,用户可以使用openmldb_tool inspect job --id x进行日志的解析提取,帮助定位错误,更多信息请参考诊断工具job检查

如果taskmanager是yarn模式,而不是local模式,job_x_error.log中的信息会较少,只会打印异常。如果异常不直观,需要更早时间的执行日志,执行日志不在job_x_error.log中,需要通过job_x_error.log中记录的yarn app id,去yarn系统中查询yarn app的container的日志。yarn app container里,执行日志也保存在stderr中。

Note

如果你无法通过show joblog获得日志,或者想要直接拿到日志文件,可以直接在TaskManager机器上获取。日志地址由taskmanager.properties的job.log.path配置,如果你改变了此配置项,需要到配置的目录中寻找日志。stdout查询结果默认在/work/openmldb/taskmanager/bin/logs/job_x.log,stderr job运行日志默认在/work/openmldb/taskmanager/bin/logs/job_x_error.log(注意有error后缀)。

集群版在线 SQL 执行注意事项#

集群版在线模式下,我们通常只推荐两种使用,DEPLOY创建deployment,执行deployment做实时特征计算(SDK请求deployment,或HTTP访问APIServer请求deployment)。在CLI或其他客户端中,可以直接在“在线”中进行SELECT查询,称为“在线预览”。在线预览有诸多限制,详情请参考功能边界-集群版在线预览模式,请不要执行不支持的SQL。

构造 OpenMLDB SQL 复现脚本#

如果你的 SQL 执行不符合预期,通过自主诊断,无法解决问题,请向我们提供复现脚本。一个完整的复现脚本。仅涉及在线SQL计算或校验SQL,推荐使用OpenMLDB SQL Emulator 构造可复现的 yaml case。如果涉及到数据导入等必须使用 OpenMLDB集群,请提供可复现脚本,其结构如下所示:

create database db;
use db;
-- create your table
create table xx ();

-- offline or online
set @@execute_mode='';

-- load data or online insert
-- load data infile '' into table xx;
-- insert into xx values (),();

-- query / deploy ...

如果你的问题需要数据才能复现,请提供数据。如果是离线数据,离线无法支持insert,请提供csv/parquet数据文件。如果是在线数据,可以提供数据文件,也可以直接在脚本中进行insert。

这样的数据脚本可以通过重定向符号,批量执行sql脚本中的命令。

/work/openmldb/bin/openmldb --host 127.0.0.1 --port 6527 < reproduce.sql
/work/openmldb/bin/openmldb --zk_cluster=127.0.0.1:2181 --zk_root_path=/openmldb --role=sql_client < reproduce.sql

请确保在你本地可以使用复现脚本复现问题,再记录issue或发送给我们。

Caution

请注意离线job默认为异步。如果你需要离线导入再查询,请设置为同步模式,详情见离线命令配置详情。否则导入还未完成就进行查询,是无意义的。

提供配置与日志,获得技术支持#

如果你的SQL执行问题无法通过复现脚本复现,或者并非SQL执行问题而是集群管理问题,那么请提供客户端和服务端的配置与日志,以便我们调查。

docker或本地的集群(服务端所有进程都在本地),可以使用诊断工具快速获取配置、日志等信息。

使用init.sh/start-all.shinit.sh standalone/start-standalone.sh脚本启动的OpenMLDB服务端,可以使用以下命令进行诊断,分别对应集群版和单机版。

openmldb_tool --env=onebox --dist_conf=cluster_dist.yml
openmldb_tool --env=onebox --dist_conf=standalone_dist.yml

cluster_dist.ymlstadnalone_dist.yml,可在docker容器/work/目录中找到,或将github目录中的yml文件复制下来使用。

如果是分布式的集群,需要配置ssh免密才能顺利使用诊断工具,参考文档诊断工具

如果你的环境无法做到,请手动获取配置与日志。

性能统计#

deployment耗时统计需要开启:

SET GLOBAL deploy_stats = 'on';

开启后的Deployment执行都将被统计,之前的不会被统计,表中的数据不包含集群外部的网络耗时,仅统计deployment在server端从开始执行到结束的时间。