在数据库中存储的数据,最终需要都需要落到磁盘上进行持久化保存。这里对 MySQL 的数据存储结构进行分析。

MySQL 中,表数据由存储引擎负责存取。下面的数据存储结构以 InnoDB 存储引擎为准。在 InnoDB 存储引擎中,数据保存在 /var/lib/mysql/ 目录下,对于创建的每个数据库,会用数据库名称创建一个同名目录。该目录中,包括 db.opt 文件存储数据库的默认字符编码等信息。另外,为每个数据表创建同名的 frm 和 ibd 两个文件。frm 文件存储数据表的元数据,包括表结构等信息。ibd 文件存储数据表的表数据,也称为表空间文件。

阅读全文 »

Slint 的应用架构如下图所示:

alt

Slint 应用使用为 UI 设计的 Slint DSL 对 UI 进行描述。这些 UI 代码通过若干 .slint 文件构成,每个 .slint 文件中可以描述若干个组件,这些组件之间进行复用,并构造一个完整的 UI 界面。

为了展示 Slint 界面,需要通过 Slint 编译器将 .slint 文件编译为 Slint 的内部表示后原生运行。这个编译的过程可以在应用程序编译时完成,也可以在程序运行时再进行。

在运行时内部,按 .slint 描述的界面元素,构成一棵 UI 元素树,在进行渲染时便基于这个 UI 元素树进行。

Slint 使用的属性、回调、模型元素也在运行时内部维护。这些元素也是应用程序代码与 UI 之间沟通的桥梁。用户界面与应用程序逻辑的交互全部通过这几类元素完成。

基于最终的 UI 元素树可以计算得到每个像素值,这些值需要展示到显示设备上。这个计算每个像素值并向显示设备传输的过程便由渲染器实现。

为了相互用户的输入,需要与输入设备交互,并将这些交互封装为输入事件传入运行时,从而分发到对应的处理函数,并产生最终的交互。

阅读全文 »

在使用数据库进行业务开发时,常常提到“事务”这一概念。这里的事务指的是对数据库的一组读写操作,并且这一系列操作需要具有 ACID 特性。

事务特性

ACID 由 Atomicity(原子性)、Consistency(一致性)、Isolation(隔离性)、Durability(持久性)四种特性组成。

Atomicity(原子性):构成事务的一组读写操作要么全部成功,要么全部失败。在成功提交时,数据修改落到数据库中,事务中的操作全部成功。当出现失败时,事务回滚将所有数据恢复到执行前的状态,所有操作全部失败。

Consistency(一致性):在数据库执行后,无论成功还是失败,数据库的完整性不会被破坏。数据库中的数据持续满足数据定义给出的要求。

Isolation(隔离性):在多个事务并发执行时,他们之间的干扰要满足一定的要求。这些不同的要求构成了不同的隔离级别。隔离级别包括:读未提交、读已提交、可重复读、可串行化。

Durability(持久性):在事务成功提交后,即使数据库管理系统发生故障,在恢复运行后,事务中提交的修改也不会丢失。

阅读全文 »

曾经编写过一篇关于 Rust 异步的文章,以非常肤浅的视角对 Rust 的异步原理进行了描述。现在将 Tokio 官方教程的其中一篇进行翻译,其中非常深入地讲解了 Rust 异步的原理。
原文链接:https://tokio.rs/tokio/tutorial/async
文章内容:
至此,我们已经完成了对异步 Rust 和 Tokio 的相当全面的介绍。现在我们将深入研究 Rust 的异步运行时模型。在本教程的一开始,我们暗示异步 Rust 采用了一种独特的方法。现在,我们来解释一下这意味着什么。

阅读全文 »

命令模块接收服务端库从客户端连接中读取的帧结构,尝试按照 Redis 支持的命令格式进行解析,从而得到 Redis 命令。成功解析得到命令后,按照 Redis 命令的语义执行动作,读写存储模块并向连接中写入帧结构作为命令的响应。

命令枚举及命令上的通用动作

在 mini-redis 项目中,实现了 Redis 的 Get、Set 等几项命令。这些命令接收不同的参数,具有不同的语义,具体的实现上也有不同。所以将支持的命令定义为枚举类型,执行命令时根据命令枚举分发到不同的类型上。但为了使用上的简便性,将这些不同命令调用包装为统一的对外接口。

阅读全文 »

与许多网络协议一样,Redis客户端和服务器端之间的通信可以使用帧结构作为基本的构成指令。mini-redis中命令模块在命令解析时就是从帧结构出发。本篇就对帧的解析进行分析和实现。

Redis客户端与服务端之间的通信,整体上属于请求-响应模型,但是引入了流水线、推送等一些特例情况。在Redis的请求和响应中具有一些固定的形态。在请求中,命令总是表示为批量字符串的的数组,响应则可以是帧结构中的各种类型。每种类型消息的第一个字节总是用来标识消息的类型。\r\n 作为协议中的终止符,用于划分不同部分。

下面是一些消息的格式或示例,在文章的后半部分需要对这些命令进行解析并封装为 Rust 中的数据结构。

1
2
3
4
5
6
+OK\r\n
-Error message\r\n
:[<+|->]<value>\r\n
$<length>\r\n<data>\r\n
_\r\n
*<number-of-elements>\r\n<element-1>...<element-n>

这些消息代表的类型分别为简单字符串、错误、整型、批量字符串、Null、数组。在 mini-redis 支持的几个命令中,利用这些帧结构即可实现支持的几个命令。

阅读全文 »

概述篇对mini-redis的模块结构进行了介绍,并构建了具有日志能力的基本项目结构。存储篇将对mini-redis的数据存储进行分析,并在存储上实现其需要对外提供的功能。

提供的功能

在分析存储模块的实现前,我们首先对存储模块所需提供的功能进行分析。mini-redis 在整体上提供了两套功能,带有过期能力的KV存储、发布-订阅功能。

在KV存储方面,需要提供根据键获取值的 get 功能和提供键、值以及可选的有效期的 set 功能。同时,需要在请求-响应之外提供按照过期时间清理过期数据的能力。

在发布-订阅方面,需要提供 subscribe 功能用于订阅特定通道,从而在给定的通道上发布消息时进行接收;还需要提供 publish 功能用于向给定的通道上发布消息。

由于不同客户端的处理任务需要共享相同的存储,存储模块需要能够在不同任务间共享,并保证线程安全。

阅读全文 »

mini-redis 是一个 Tokio 编程示例性质的项目,其中演示了一些 Tokio 异步编程模式。在进行网络编程时,我们可以参考这些示例使用这些模式。下面我们对 mini-redis 的源码进行分析,并学习其中的异步网络编程模式。并在充分理解的基础上对其进行重新实现。

我们将仓库的实现层次整体绘制为下图所示的架构图。

mini-redis Architecture

阅读全文 »
0%