专栏首页99+服务器优惠在 libevent 中使用 MariaDB(MySQL)
原创

在 libevent 中使用 MariaDB(MySQL)

[腾讯云服务器 年付3折起【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起

https://cloud.tencent.com/act/cps/redirect?redirect=1044&cps_key=77574b69e8df2ded58bab0c089537a58&from=console

首次购买云服务器 最低3折起 超高性价比【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起

https://cloud.tencent.com/act/cps/redirect?redirect=1044&cps_key=77574b69e8df2ded58bab0c089537a58&from=console

限时抢购【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起

https://cloud.tencent.com/act/cps/redirect?redirect=1044&cps_key=77574b69e8df2ded58bab0c089537a58&from=console

  • 基本流程
  • 流程状态图
  • 详细流程
    • Connect 阶段
    • Query 阶段
    • Use Result 阶段
    • Fetch Row 阶段
    • Close 阶段
    • Exit 阶段
  • 阻塞函数改造
    • 状态机函数
    • 状态机流转
  • 完整状态图
  • 参考资料

在之前我翻译的官方文档(【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起

https://cloud.tencent.com/act/cps/redirect?redirect=1044&cps_key=77574b69e8df2ded58bab0c089537a58&from=console)中提到了 MariaDB(【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起

https://cloud.tencent.com/act/cps/redirect?redirect=1044&cps_key=77574b69e8df2ded58bab0c089537a58&from=console) 提供了对异步 I/O 的支持。那篇文章是一个比较简要的介绍。不过实际适配中,官方也提供了一个完整适配 libevent 的示例代码(【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起

https://cloud.tencent.com/act/cps/redirect?redirect=1044&cps_key=77574b69e8df2ded58bab0c089537a58&from=console)。本文算是对我上述示例代码的阅读笔记吧。

阅读本文之前,作者假设读者已经有了 libevent 的相关知识。如果没有的话,可以参见我的系列文章:

此外本文内容也适合其他的异步 I/O 库,如:


**基本流程【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起

https://cloud.tencent.com/act/cps/redirect?redirect=1044&cps_key=77574b69e8df2ded58bab0c089537a58&from=console**

传统的 MySQL client 在请求 DB 查询的时候,API 调用流程为:

mysql_real_connect()
mysql_real_query()
mysql_use_result()
mysql_fetch_row()
mysql_close()

不过,在异步 socket 模型中,根据官方介绍文档中也提及了,对于会产生阻塞的函数调用 XXX,需要分开 XXX_start()XXX_cont() 进行调用。上述流程中,除了 mysql_use_result() 不是阻塞调用之外,其他的函数均需要如此区分。


流程状态图

异步服务器经常是以状态图模式进行设计开发的,官方 demo 是基于 libevent 设计的,也一样。下面是简化版的流程装态图(流程图 + 状态图):

上图主要是正常流程,异常流程暂未列出。实线表示该状态的流转需要经过异步 I/O 等待(libevent 调用 event_add())后才能获取相应的状态码或返回值进行检查后才可以进行的状态流转,虚线表示在该状态下即已有足够的变量可进行状态流转。


*详细流程【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起

https://cloud.tencent.com/act/cps/redirect?redirect=1044&cps_key=77574b69e8df2ded58bab0c089537a58&from=console*

Connect 阶段

该阶段包含三个状态,其中两个状态分别是 mysql_real_connect_start()mysql_real_connect_cont() 函数的调用状态。这两个函数之间的流转,后文 “阻塞函数改造” 小节中再做说明。

mysql_real_connect 系列函数返回 status == 0 之后,程序就可以流转到该阶段的第三个状态,在代码中的状态码是 9。这个状态中,程序只进行异常判断,如果正常,则流转至下一流程 query 阶段。如果在状态 9 检测到异常,程序中直接调用 exit() ,因此可以认为这个状态极少出错。当然对于正式的程序,还是需要捕捉这个错误的。

【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起

https://cloud.tencent.com/act/cps/redirect?redirect=1044&cps_key=77574b69e8df2ded58bab0c089537a58&from=console

Query 阶段

该阶段包含两个状态,分别是 mysql_real_query_start()mysql_real_query_cont() 函数的调用状态。这两个状态的代码就是非常典型的 _start + _cont 阶段。后文将会说明相关内容。

另外,在 mysql_real_query_start() 处,还会检查当前是否有新的查询请求。如果没有请求,则会直接进入 close 阶段。这与普通的 MySQL 流程无异,因此不展开讲。

Use Result 阶段

这个阶段调用的是 muysql_use_result() 函数。由于该函数不是阻塞函数,因此该阶段只需要一个状态,并且状态的流转不需要等待,直接流转即可。

Fetch Row 阶段

【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起

https://cloud.tencent.com/act/cps/redirect?redirect=1044&cps_key=77574b69e8df2ded58bab0c089537a58&from=console

该阶段向数据库获取结果的行,同样有相应的 _start()_cont() 状态,这两个阶段同样后文再讲述。在 _cont() 状态中如果 status 值为 0,则直接进入 39 状态使用获得的数据进行操作。

39 状态中,如果数据未获取完,则继续回到该阶段的 _start() 状态;如果当前叉裙已经结束,则回到 query 阶段。

Close 阶段

【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起

https://cloud.tencent.com/act/cps/redirect?redirect=1044&cps_key=77574b69e8df2ded58bab0c089537a58&from=console

如前文所述,该阶段的入口是从 query 阶段而来。和普通的 socket close 不同,MySQL client 的 close 操作是阻塞的,需要将这个阶段的代码改造成异步模式。和 query 阶段类似,该阶段只需要 _start()_cont() 两个状态即可

Exit 阶段

【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起

https://cloud.tencent.com/act/cps/redirect?redirect=1044&cps_key=77574b69e8df2ded58bab0c089537a58&from=console

这个阶段其实不是 MySQL 的请求流程之一,而是整个应用程序的流程阶段。在这个阶段,应用程序需要调用其所使用的异步 I/O 框架的退出机制。对于 libevent,则是 event_loopbreak()


阻塞函数改造

状态机函数

上文所提及的几个阶段中,有四个阶段是对原有阻塞函数的改造,需要将阻塞函数分为同名的 _start()_cont() 两个函数。以 mysql_real_connect() 函数为例,该函数需要改造为 mysql_real_connect_start()mysql_real_connect_cont() 两个函数。其中 _start 发起流程,而 _cont 表示 “continue”,则是处理异步 I/O 过程中的一些(不需要程序员关心)的中间状态,同时判断异步 I/O 是否已经完成。

这里需要的两个函数分别是:

// 仅声明异步改造的关键变量
【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起
https://cloud.tencent.com/act/cps/redirect?redirect=1044&cps_key=77574b69e8df2ded58bab0c089537a58&from=console
// _start 状态
int status;
MYSQL mysql;
MYSQL *mysql_ret;
status = mysql_real_connect_start(&mysql_ret, host, user, passwd, db_name, port, unix_sock, 0);

// _cont 状态
int status;
MYSQL mysql;
MYSQL *mysql_ret;
status = mysql_real_connect_cont(&mysql_ret, &MYSQL, _libevent_to_mysql_status(libevent_what));

// _libevent_to_mysql_status 转换函数
static int _libevent_to_mysql_status(short event)
{
    int status= 0;
    if (event & EV_READ)
        status|= MYSQL_WAIT_READ;
    if (event & EV_WRITE)
        status|= MYSQL_WAIT_WRITE;
    if (event & EV_TIMEOUT)
        status|= MYSQL_WAIT_TIMEOUT;
    return status;
}

其中 start 函数的后七个参数,与原本 mysql_real_query 相同。而第一个参数 &mysql_ret ,则替代了原函数的返回值的作用。而 _start() 函数的返回值,则换成一个 int 类型的变量,用于适配异步 I/O。该 int 变量是一个位掩码变量,与 libevent 事件回调函数中的 short what 变量的位掩码一一对应(参见上文 _libevent_to_mysql_status() 函数,等同于官方 demo 中的 mysql_status() 函数)

状态机流转

【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起

https://cloud.tencent.com/act/cps/redirect?redirect=1044&cps_key=77574b69e8df2ded58bab0c089537a58&from=console

状态机中写好了基本的调用函数之后,接下来就需要判断状态机的流转条件了。参见下图:

流转条件集中针对两个 “返回值” 的状态进行流转:

  • 异步 MySQL API 的 int 类型返回值 status:如果返回零,则表示当前操作正常完成,可走入下一步;如果非零,则表示下一步需要的事件掩码,在 _cont() 函数上继续等待
  • 原阻塞函数的返回值,也即异步 API 的第一个参数:处理方式以原阻塞式函数的处理方式相同。

转换为 libevent 掩码

状态流转时,如果需要等待 I/O 操作,那么需要使用异步 I/O 框架的事件函数进行操作。在 MySQL 异步 API 中,其状态值与 libevent 的掩码值是一一对应的。在前文 _libevent_to_mysql_status() 函数中已经体现了,对应关系如下:

类型

含义

MySQL 值或类型

libevent 值或类型

位掩码

读事件

MYSQL_WAIT_READ

EV_READ

位掩码

写事件

MYSQL_WAIT_WRITE

EV_WRITE

位掩码

超时时间

MYSQL_WAIT_TIMEOUT

EV_TIMEOUT

变量

socket 文件描述符

mysql_get_socket(&mysql)

evutil_socket_t fd

变量

超时事件

mysql_get_timeout_value(&mysql)

struct timeval

有了上述对应关系,已经足以将 MySQL 的变量转为 event_set()event_add() 函数调用了。

这样,一个完整的基于异步 I/O 框架的 MySQL client 过程,就建立起来了。

【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起

https://cloud.tencent.com/act/cps/redirect?redirect=1044&cps_key=77574b69e8df2ded58bab0c089537a58&from=console


完整状态图

下面附上完整的状态图,能够更加直观地浏览整个异步状态:

【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起

https://cloud.tencent.com/act/cps/redirect?redirect=1044&cps_key=77574b69e8df2ded58bab0c089537a58&from=console


参考资料

----【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起

https://cloud.tencent.com/act/cps/redirect?redirect=1044&cps_key=77574b69e8df2ded58bab0c089537a58&from=console

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

相关文章

  • 【新手教程】手把手教你搭建腾讯云服务器

        暑假期间,愁着无聊但也不能荒废学业吧,毕竟以后想靠技术混口饭吃!为了实施自己的计划,特地挑了一个便宜的云服务器来用作自己的后台;这不是学生狗没钱嘛,所以...

    赤孺
  • 如何购买腾讯云服务器

    官网购买地址热卖云产品3折起,云服务器、云数据库特惠,服务更稳,速度更快,价格更优【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起

    赤孺
  • 企业如何选择腾讯云服务器配置?

    腾讯云服务器 年付3折起【新用户限量秒杀】热门云产品限量秒杀,云服务器1核2G 16.5元/月起

    赤孺
  • MySql 利用mysql&mysqldum导入导出数据

    mysqldump,该命令位于mysql/bin/目录中:..../mysql/bin/mysqldump

    授客
  • ppt怎么转换为pdf?这个方法教你10秒搞定!

    PPT怎么转换为PDF?我们在日常的工作当中,经常用到PPT,用来演示演讲,但是有的时候我们需要把PPT的内容放到PDF当中,就需要将PPT转换成PDF,怎么做...

    高效办公
  • ECMAScript 2018 标准导读

    https://segmentfault.com/a/1190000009914740

    前端博客 : alili.tech
  • JUnit 5 测试问题 must be static unless the test class is

    为了允许隔离执行单个的测试方法,并避免由于可变测试实例状态而产生的意外副作用,JUnit在执行每个测试方法之前创建每个测试类的新实例(请参阅下面的讲解,何为测试...

    HoneyMoose
  • Java自动化测试(allure 20)

    zx钟
  • 3分钟了解清楚持续集成、持续交付、持续部署

    近些年来,持续集成、持续交付以及持续部署这几个热词总是在大家的眼前晃来晃去!在招聘信息和面试过程中也会经常提及!在这里我就用三分钟时间来带大家了解他们!

    测试开发技术
  • 惊艳!Facebook未来十年愿景!

    大数据文摘

扫码关注云+社区

领取腾讯云代金券