OpenM(ysq)LDB 项目介绍

OpenM(ysq)LDB 是高性能时序数据库 OpenMLDB 的全新服务模块,OpenMLDB 中 “ML” 既是 Machine Learning 的缩写,也可以是 MySQL 的缩写,通过此模块用户可以直接使用 MySQL 命令行客户端或多种编程语言的 MySQL SDK,从而实现 OpenMLDB 数据库特有的在线离线特征计算功能。

OpenMLDB 是基于 C++ 和 LLVM 实现的分布式高性能内存时序数据库,在架构设计和实现逻辑上与专注于单机的关系型数据库 MySQL 有很大区别,并且 OpenMLDB 更加适用于金融风控、推荐系统等硬实时在线特征计算场景中。由于二者都提供标准的 ANSI SQL 接口,OpenMLDB 通过兼容 MySQL 协议,让客户直接使用熟悉的 MySQL 客户端,甚至在Java、Python 等 SDK 编程中也不需要修改业务代码,可直接用 MySQL 库来访问 OpenMLDB 数据以及执行特殊的 OpenMLDB SQL 特征抽取语法。

使用兼容的 MySQL 命令行

部署 OpenMLDB 分布式集群以后,开发者不需要额外安装 OpenMLDB 命令行工具,使用预安装好的 MySQL 命令行工具,可直接连接 OpenMLDB 集群进行测试(注意,以下 SQL 连接以及执行结果均在 OpenMLDB 集群中返回,并非 MySQL 服务)。

file

通过执行定制化的 OpenMLDB SQL,我们不仅可以查看 OpenMLDB 集群状态,还可以切换离线模式和在线模式,实现 MLOps 的离线和在线特征抽取功能。

file

使用兼容的 JDBC 驱动

Java 用户一般使用 MySQL JDBC 驱动来连接 MySQL,同样的代码不需要任何修改就可以直连 OpenMLDB 集群。

编写 Java 应用代码如下,注意根据实际集群情况修改IP、端口以及用户名密码信息。

public class Main {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3307/db1";
        String user = "root";
        String password = "root";

        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;

        try {
            connection = DriverManager.getConnection(url, user, password);
            statement = connection.createStatement();

            resultSet = statement.executeQuery("SELECT * FROM db1.t1");

            while (resultSet.next()) {
                int id = resultSet.getInt("id");
                String name = resultSet.getString("name");
                System.out.println("ID: " + id + ", Name: " + name);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // Close the result set, statement, and connection
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (statement != null) {
                    statement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

然后编译执行即可,可以在命令行输出中看到查询的 OpenMLDB 数据库数据。

file

使用兼容的 SQLAlchemy 驱动

Python 用户常使用 SQLAlchemy 和 MySQL 驱动,同样的代码也可以直接用于查询 OpenMLDB 的在线数据。

编写 Python 应用代码如下:

from sqlalchemy import create_engine, text

def main():
    engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3307/db1", echo=True)
    with engine.connect() as conn:
        result = conn.execute(text("SELECT * FROM db1.t1"))
        for row in result:
            print(row)

if __name__ == "__main__":
  main()

然后直接执行,在命令行也可以看到对应的 OpenMLDB 数据库输出。

file

使用兼容的 Go MySQL 驱动

Golang 用户一般官方推荐的 github.com/go-sql-driver/mysql 驱动来访问 MySQL,同样不需要修改应用代码就可以直接访问 OpenMLDB 集群。

编写 Golang 应用代码如下:

package main

import (
        "database/sql"
        "fmt"
        "log"

        _ "github.com/go-sql-driver/mysql"
)

func main() {
        // MySQL database connection parameters
        dbUser := "root"         // Replace with your MySQL username
        dbPass := "root"         // Replace with your MySQL password
        dbName := "db1"    // Replace with your MySQL database name
        dbHost := "localhost:3307"        // Replace with your MySQL host address
        dbCharset := "utf8mb4"            // Replace with your MySQL charset

        // Create a database connection
        db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=%s", dbUser, dbPass, dbHost, dbName, dbCharset))
        if err != nil {
                log.Fatalf("Error connecting to the database: %v", err)
        }
        defer db.Close()

        // Perform a simple query
        rows, err := db.Query("SELECT id, name FROM db1.t1")
        if err != nil {
                log.Fatalf("Error executing query: %v", err)
        }
        defer rows.Close()

        // Iterate over the result set
        for rows.Next() {
                var id int
                var name string
                if err := rows.Scan(&id, &name); err != nil {
                        log.Fatalf("Error scanning row: %v", err)
                }
                fmt.Printf("ID: %d, Name: %s\n", id, name)
        }
        if err := rows.Err(); err != nil {
                log.Fatalf("Error iterating over result set: %v", err)
        }
}

直接编译并运行,即可在命令行查看数据库输出的结果。

file

使用兼容的 Sequel Ace 客户端

MySQL 用户常用 GUI 应用来简化数据库的管理,用户如果想要连接 OpenMLDB 集群,也可以使用这类开源的 GUI 工具。

以 Sequel Ace 为例,用户不需要修改任何项目代码,只需要在连接数据库时,地址和端口填写 OpenM(ysq)LDB 服务的地址和端口,用户名和密码填写 OpenMLDB 服务的用户名和密码,即可按照 MySQL 的操作方法来访问 OpenMLDB 服务。

file

使用兼容的 Navicat 客户端

除了 Sequel Ace ,Navicat 也是比较受欢迎的MySQL客户端,用户不需要修改任何项目代码,只需要新建连接(MySQL) 时,地址和端口填写 OpenM(ysq)LDB 服务的地址和端口,用户名和密码填写 OpenMLDB 服务的用户名和密码,即可按照 MySQL 的操作方法来访问 OpenMLDB 服务。

file

MySQL 协议兼容原理

MySQL(包括后续 MariaDB 版本)的协议都是公开可读的,OpenM(ysq)LDB 在服务端完全实现并兼容了 MySQL 的协议,并且通过 OpenMLDB 的 SDK 来管理后端访问分布式 OpenMLDB 集群的连接,从而实现与各种 MySQL 客户端的兼容访问。

file

目前 OpenM(ysql)LDB 通过长连接的维护客户端与 OpenMLDB 的交互,保证每个连接都有唯一的客户端对象访问 OpenMLDB 集群,相同连接的所有 SQL 查询都不需要额外初始化,并且在连接关闭后自动释放资源,服务本身占用的开销几乎可以忽略不计,性能与直连 OpenMLDB 也可以保持一致。

更多使用文档可参考官方文档 https://openmldb.ai/docs/zh/main/app_ecosystem/open_mysql_db/index.html

总结

OpenM(ysql)LDB 是 OpenMLDB 项目的一次大胆的尝试,在 0.1.5 到 0.8.5 一共39个版本发布后,在不断的功能完善和 SQL 语法兼容以后,终于实现了完全兼容 MySQL 协议的功能,在保证了基本的 SQL 查询功能外还提供了比 MySQL 更高性能的底层存储实现和 AI 能力拓展。从此以后,MySQL / MariaDB 用户可以无缝地切换他们的数据库存储引擎,不同编程语言的开发者也可以直接使用已有成熟的 MySQL SDK,使用 OpenMLDB 服务的门槛极度降低,为所有 DBA 或数据开发者提供向 AI 转型的“捷径”。

注意,目前测试 MySQL Workbench 暂无法使用 OpenM(ysql)LDB,相关测试工作仍在进行中,感兴趣的开发者可以在 Github 上持续关注此项目的开发进展。

相关阅读