目录
一、引言
1. 编写目的
2. 需求概述
3. 软件结构
4. 参考资料
二、概要设计
1. 架构设计
2. 流程图
三、详细设计
1. 功能设计
2. 性能设计
3. 功能限制
四、总结
一、引言
编写目的
需求概述
软件结构
参考资料
二、概要设计
架构设计
流程图
三、详细设计
功能设计
对外接口
开关控制命令(du_flow_control)
用于控制限流功能是否启用。
大小写敏感命令(du_flow_control_case_sensitive)
用于控制限流规则匹配时是否大小写敏感。
预留用户命令(du_flow_control_reserve_user)
限流功能对于预留用户不生效。 预留用户参数以字符串的形式接受输入,如果存在多个预留用户,使用 ',' 进行分隔。 在服务启动时,需格式化该参数,后续在做限流判断时,需要根据格式化之后参数识别是否是预留用户,如果是预留用户,则不进行限流操作,无需进行后续的限流规则匹配。 预留用户参数接受NULL和空串 '',当该参数为NULL或空串时,表明所有用户都不是预留用户。 对于预留用户字符串的处理,与MySQL社区对于用户名的处理逻辑保持一致,即忽略每个用户名前后的无意义字符(如空格、换行等),保留用户名之间的无意义字符。 分隔符设置命令(du_flow_control_delimiter)
用于控制限流规则的分隔符。 分隔符不可为空,且长度小于等于1024。 修改分隔符之后,需要重新加载限流规则,对限流规则进行解析,会消耗系统资源,因此不建议在系统负载过高时修改分隔符。
// 更新
static bool update_delimiter(sys_var *self, THD *thd, enum_var_type type)
{
reload_rules(thd);
}
// 校验
static bool check_delimiter(sys_var *self, THD *thd, set_var *var)
{
judge(var->value);
judge(str);
judge(length);
}
功能模块详细设计
规则管理
读取
主动执行自定义读取命令,用于更新限流规则到内存。每当添加限流规则后,需手动执行该操作,更新限流规则到内存。 修改分隔符时。修改分隔符后,限流规则需要重新解析,因此也需要重新读取。 数据库实例启动时。基于性能考虑,在实例启动时,将限流规则加载到内存中。 移除
系统停止时移除限流规则时。 手动删除限流规则时。 解析
将物理表中的限流规则字符串读取到内存字符串中。 根据分隔符将字符串解析为关键字组成的模式串链表。 流程控制
启动时: 加载、解析限流规则到内存中。 解析预留用户。
int mysqld_main(int argc, char **argv)
{
...
load_rules();
...
}
执行时: 在具体执行语句之前对查询语句进行判断,如果当前的执行线程是复制相关的系统线程、存储过程和方法、用户是预留用户,则无需进行规则匹配;否则,根据规则匹配的结果来决定是否进行SQL限流。 匹配的效率与限流规则的数量、大小、查询串的大小都有关系,由于此时解析完成的限流规则都已在内存中,因此整个匹配过程消耗资源较少。但还是建议用户设置的限流规则更加通用、长度更短、数量更少,这样更能提高限流功能的执行效率。 查询执行完成后,维护对应限流规则的当前并发度。具体实现为在thd中添加id字段,在进行限流时,id为非0值,如果在流程中判断id非0,且限流功能已开启,则在限流规则中查找,根据规则节点的id与thd->id进行匹配,如果存在匹配的限流规则,则将其当前并发度减一。
void dec_conc(THD *thd, int command)
{
// 根据查询类型在对应链表找节点
node = find_by_id(list, thd->id);
// 并发数量减1
if (node) {
__sync_sub_and_fetch(&(node->concur), 1);
}
// 重置状态
thd->id = 0;
}
关闭时:
void clean_up()
{
cleanup();
}
限流匹配
根据DB判断是否是对系统表的查询,如果是对系统表的查询,不做限流。
/* The flow control does not take effect on system tables */
if (check_system_table(first_table->db)) {
return ret;
}
针对不同的操作类型,在相应的限流规则链表上做模式匹配。 获取并解析链表上的节点,根据链表节点中保存的关键字串与查询串匹配; 如果关键字串都匹配到,则匹配成功。
bool check_rule_matched(THD* thd, LIST* list)
{
while (满足条件,无异常) {
// 根据大小写开关是否打开,分别进行模式串匹配
it = find(query_str, item->key_array[nums]);
// 如果it为空,没有匹配到,查看下一个list,否则继续匹配当前限流规则节点
judge();
}
// 匹配成功,或者对下一个节点进行匹配
}
在匹配过程中维护原子变量cur_concur、cur_reject、total_reject,分别表示当前并发数、当前限流次数、总的限流次数,用以判断是否需要进行限流以及在系统运行期间观察SQL限流的执行状态。 数据获取
class Du_table_access {
public:
Du_table_access() : m_drop_thd_object(NULL) {}
virtual ~Du_table_access() {}
// 初始化打开表的环境、锁表并且打开表
bool init(THD **thd, TABLE **table, bool is_write);
// 关闭表,清理环境
bool deinit(THD *thd, TABLE *table, bool error, bool need_commit);
// 设置打开表的策略
void before_open(THD *thd);
// 如果需要的话创建线程,大部分时候并不需要,因为手动执行读取数据的时候已经在线程中了
THD *create_thd();
// 如果手动创建了 thd,则需要手动清理
void drop_thd(THD *thd);
};
限流规则表设计
定义系统表保存限流规则,表格式如下:
SET @cmd= "CREATE TABLE IF NOT EXISTS du_flow_control_rules (
id BIGINT NOT NULL AUTO_INCREMENT COMMENT 'Id of the flow control rules.',
type ENUM('SELECT', 'UPDATE', 'INSERT', 'DELETE') CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'Type of flow control rules.',
max_concur INT NOT NULL COMMENT 'Max concurrent of sql.',
orig_str VARCHAR(1024) CHARSET SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'Original string of flow control rules.',
PRIMARY KEY(id)) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT 'Flow control rules info.'";
SET @str=IF(@have_innodb <> 0, CONCAT(@cmd, ' ENGINE= INNODB;'), CONCAT(@cmd, ' ENGINE= MYISAM;'));
PREPARE stmt FROM @str;
EXECUTE stmt;
DROP PREPARE stmt;
权限与格式控制
DELIMITER $$
CREATE DEFINER='root'@'localhost' PROCEDURE mysql.add_flow_control ( IN sql_type INT, IN str VARCHAR(1024), IN max_num INT )
COMMENT '
Description
-----------
Basic functions for inserting rules.
It is not recommended to call it directly, but to call it through add_select_flow_control、
add_update_flow_control、add_update_flow_control and add_delete_flow_control.
'
SQL SECURITY INVOKER
BEGIN
IF (sql_type = 0) THEN
INSERT INTO mysql.du_flow_control_rules(type, max_concur, orig_str) VALUES('SELECT', max_num, str);
ELSEIF (sql_type = 1) THEN
INSERT INTO mysql.du_flow_control_rules(type, max_concur, orig_str) VALUES('UPDATE', max_num, str);
ELSEIF (sql_type = 2) THEN
INSERT INTO mysql.du_flow_control_rules(type, max_concur, orig_str) VALUES('INSERT', max_num, str);
ELSEIF (sql_type = 3) THEN
INSERT INTO mysql.du_flow_control_rules(type, max_concur, orig_str) VALUES('DELETE', max_num, str);
ELSE
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Sql type is error, please input correctly.';
END IF;
END$$
CREATE DEFINER='root'@'localhost' PROCEDURE mysql.add_select_flow_control (IN str VARCHAR(1024), IN max_num INT )
COMMENT '
Description
-----------
Used to add select type rules to the current rule table.
Parameters
-----------
str (VARCHAR(1024)):
The string of select rules entered by user.
max_num (INT):
The number of queries that can be executed concurrently.
Example
--------
mysql> SELECT * FROM du_flow_control_rules;
Empty set (0.00 sec)
mysql> CALL add_select_flow_control(''select~from~t1'', 100);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM du_flow_control_rules;
+----+--------+------------+----------------+
| id | type | max_concur | orig_str |
+----+--------+------------+----------------+
| 1 | SELECT | 100 | select~from~t1 |
+----+--------+------------+----------------+
1 row in set (0.00 sec)
'
SQL SECURITY INVOKER
BEGIN
CALL add_flow_control(0, str, max_num);
END$$
DELIMITER ;
性能设计
刷新限流规则到节点时,为了提升加载效率,节省不必要的遍历,使用MySQL原生的链表插入方法,且只增删限流规则,不允许修改限流规则。具体流程为,在限流规则节点增加ID字段,该字段与规则表中的自增主键ID对应,即该字段递增。 在从系统表中读取数据后,根据ID可以快速判断出该条记录该插入的情况,此时对于该条记录,可能有两种场景:一是该条记录已经加载并解析到内存(链表中存在该节点),无需再次插入;二是这条记录还没有加载到内存,找到对应位置插入即可。 在数据库实例启动时,从已有系统表中加载一次数据,提升后续限流效率。 使用方面: 由于分隔符的选择决定了限流规则的不同形式,因此修改分隔符会导致限流规则全部重新加载解析一次,尽量不在业务高峰期修改分隔符。 SQL限流的性能取决于限流规则的数量、关键字数量、查询的单词数量,因此在使用时,应尽量使用较为通用的限流规则。
功能限制
在添加SQL限流规则之前,已经开始执行的SQL语句,不会被记入并发数; 存储过程、触发器、函数和对系统表的查询不受SQL限流的限制; 当设置过多限流规则时,对性能有一定影响。
四、总结
如喜欢本文,请点击右上角,把文章分享到朋友圈
如有想了解学习的技术点,请留言给若飞安排分享
因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享
·END·
相关阅读:
一张图看懂微服务架构路线 基于Spring Cloud的微服务架构分析 微服务等于Spring Cloud?了解微服务架构和框架 如何构建基于 DDD 领域驱动的微服务? 微服务架构实施原理详解 微服务的简介和技术栈 微服务场景下的数据一致性解决方案 设计一个容错的微服务架构
作者:Peter
来源:得物技术
版权申明:内容来源网络,仅供学习研究,版权归原创者所有。如有侵权烦请告知,我们会立即删除并表示歉意。谢谢!
我们都是架构师!
关注架构师(JiaGouX),添加“星标”
获取每天技术干货,一起成为牛逼架构师
技术群请加若飞:1321113940 进架构师群
投稿、合作、版权等邮箱:admin@137x.com