自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

基于MySQL內(nèi)核的SQL限流設(shè)計(jì)與實(shí)現(xiàn)

數(shù)據(jù)庫(kù) MySQL
本文詳細(xì)描述了基于MySQL內(nèi)核的SQL限流功能的整體架構(gòu)、主要功能模塊等關(guān)鍵要素。SQL限流的設(shè)計(jì)與實(shí)現(xiàn)基于原生MySQL的執(zhí)行原理與字符串匹配規(guī)則實(shí)現(xiàn)。

一、引言

編寫目的

本文詳細(xì)描述了SQL限流特性的需求設(shè)計(jì)方案以及使用方式,開發(fā)、測(cè)試人員可根據(jù)本文實(shí)現(xiàn)功能的開發(fā)、測(cè)試,DBA可根據(jù)本文合理使用SQL限流功能。

需求概述

生產(chǎn)環(huán)境中可能出現(xiàn)由于業(yè)務(wù)量增長(zhǎng)過快或者慢SQL等原因?qū)е翪PU使用率打滿,當(dāng)CPU打滿時(shí),會(huì)影響所有依賴該數(shù)據(jù)庫(kù)實(shí)例的業(yè)務(wù),因此需要有手段限制影響CPU的業(yè)務(wù)執(zhí)行,保證其他核心業(yè)務(wù)不受影響。

SQL限流的目標(biāo)是在出現(xiàn)CPU使用率打滿影響所有業(yè)務(wù)時(shí),通過限制非核心業(yè)務(wù)或者慢SQL的業(yè)務(wù),實(shí)現(xiàn)核心業(yè)務(wù)的快速恢復(fù)。

軟件結(jié)構(gòu)

MySQL軟件結(jié)構(gòu)如下圖所示:

圖片圖片

參考資料

MySQL官網(wǎng):https://dev.mysql.com/doc/refman/5.7/en/

二、概要設(shè)計(jì)

架構(gòu)設(shè)計(jì)

圖片圖片

總體架構(gòu)如圖所示,SQL限流的主要功能在執(zhí)行器工作階段通過限流規(guī)則與查詢串的匹配來實(shí)現(xiàn)。

流程圖

圖片圖片

三、詳細(xì)設(shè)計(jì)

功能設(shè)計(jì)

對(duì)外接口

針對(duì)SQL限流功能設(shè)計(jì)對(duì)外提供管理命令,如下:

  • 開關(guān)控制命令(du_flow_control)

圖片圖片

用于控制限流功能是否啟用。

  • 大小寫敏感命令(du_flow_control_case_sensitive)

圖片圖片

用于控制限流規(guī)則匹配時(shí)是否大小寫敏感。

  • 預(yù)留用戶命令(du_flow_control_reserve_user)

圖片圖片

限流功能對(duì)于預(yù)留用戶不生效。

預(yù)留用戶參數(shù)以字符串的形式接受輸入,如果存在多個(gè)預(yù)留用戶,使用 ',' 進(jìn)行分隔。

在服務(wù)啟動(dòng)時(shí),需格式化該參數(shù),后續(xù)在做限流判斷時(shí),需要根據(jù)格式化之后參數(shù)識(shí)別是否是預(yù)留用戶,如果是預(yù)留用戶,則不進(jìn)行限流操作,無需進(jìn)行后續(xù)的限流規(guī)則匹配。

預(yù)留用戶參數(shù)接受NULL和空串 '',當(dāng)該參數(shù)為NULL或空串時(shí),表明所有用戶都不是預(yù)留用戶。

對(duì)于預(yù)留用戶字符串的處理,與MySQL社區(qū)對(duì)于用戶名的處理邏輯保持一致,即忽略每個(gè)用戶名前后的無意義字符(如空格、換行等),保留用戶名之間的無意義字符。

  • 分隔符設(shè)置命令(du_flow_control_delimiter)

圖片圖片

用于控制限流規(guī)則的分隔符。

分隔符不可為空,且長(zhǎng)度小于等于1024。

修改分隔符之后,需要重新加載限流規(guī)則,對(duì)限流規(guī)則進(jìn)行解析,會(huì)消耗系統(tǒng)資源,因此不建議在系統(tǒng)負(fù)載過高時(shí)修改分隔符。

對(duì)于預(yù)留用戶的處理,核心功能如下:

// 更新
static bool update_delimiter(sys_var *self, THD *thd, enum_var_type type)
{
  reload_rules(thd);
}


// 校驗(yàn)
static bool check_delimiter(sys_var *self, THD *thd, set_var *var)
{
  judge(var->value);
  judge(str);
  judge(length);
}

功能模塊詳細(xì)設(shè)計(jì)

  • 規(guī)則管理

SQL限流使用的場(chǎng)景為CPU負(fù)載過高,為了防止加重系統(tǒng)的負(fù)擔(dān),限流規(guī)則應(yīng)該事先加載到內(nèi)存中?;诖耍枰獙?duì)內(nèi)存中的限流規(guī)則進(jìn)行管理,涉及的操作有:規(guī)則的讀取、移除、解析。

讀取

規(guī)則讀取的場(chǎng)景有:

  • 主動(dòng)執(zhí)行自定義讀取命令,用于更新限流規(guī)則到內(nèi)存。每當(dāng)添加限流規(guī)則后,需手動(dòng)執(zhí)行該操作,更新限流規(guī)則到內(nèi)存。
  • 修改分隔符時(shí)。修改分隔符后,限流規(guī)則需要重新解析,因此也需要重新讀取。
  • 數(shù)據(jù)庫(kù)實(shí)例啟動(dòng)時(shí)。基于性能考慮,在實(shí)例啟動(dòng)時(shí),將限流規(guī)則加載到內(nèi)存中。

移除

規(guī)則移除的場(chǎng)景有:

  • 系統(tǒng)停止時(shí)移除限流規(guī)則時(shí)。
  • 手動(dòng)刪除限流規(guī)則時(shí)。

解析

用戶輸入的規(guī)則在物理表中的表現(xiàn)是一個(gè)字符串,在將其加載到內(nèi)存時(shí),需要根據(jù)限流規(guī)則的分隔符將其解析為對(duì)應(yīng)的規(guī)則模式串,在模式串中包含的關(guān)鍵字全部被滿足時(shí),需要進(jìn)行限流。解析過程如下:

  • 將物理表中的限流規(guī)則字符串讀取到內(nèi)存字符串中。
  • 根據(jù)分隔符將字符串解析為關(guān)鍵字組成的模式串鏈表。
  • 流程控制

SQL限流的的流程控制添加在SQL執(zhí)行階段,主要的內(nèi)容有:

啟動(dòng)時(shí):

  • 加載、解析限流規(guī)則到內(nèi)存中。
  • 解析預(yù)留用戶。
int mysqld_main(int argc, char **argv)
{
  ...
  load_rules();
  ...
}

執(zhí)行時(shí):

  • 在具體執(zhí)行語(yǔ)句之前對(duì)查詢語(yǔ)句進(jìn)行判斷,如果當(dāng)前的執(zhí)行線程是復(fù)制相關(guān)的系統(tǒng)線程、存儲(chǔ)過程和方法、用戶是預(yù)留用戶,則無需進(jìn)行規(guī)則匹配;否則,根據(jù)規(guī)則匹配的結(jié)果來決定是否進(jìn)行SQL限流。匹配的效率與限流規(guī)則的數(shù)量、大小、查詢串的大小都有關(guān)系,由于此時(shí)解析完成的限流規(guī)則都已在內(nèi)存中,因此整個(gè)匹配過程消耗資源較少。但還是建議用戶設(shè)置的限流規(guī)則更加通用、長(zhǎng)度更短、數(shù)量更少,這樣更能提高限流功能的執(zhí)行效率。
  • 查詢執(zhí)行完成后,維護(hù)對(duì)應(yīng)限流規(guī)則的當(dāng)前并發(fā)度。具體實(shí)現(xiàn)為在thd中添加id字段,在進(jìn)行限流時(shí),id為非0值,如果在流程中判斷id非0,且限流功能已開啟,則在限流規(guī)則中查找,根據(jù)規(guī)則節(jié)點(diǎn)的id與thd->id進(jìn)行匹配,如果存在匹配的限流規(guī)則,則將其當(dāng)前并發(fā)度減一。
void dec_conc(THD *thd, int command)
{
  // 根據(jù)查詢類型在對(duì)應(yīng)鏈表找節(jié)點(diǎn)
  node = find_by_id(list, thd->id);


  // 并發(fā)數(shù)量減1
  if (node) {
    __sync_sub_and_fetch(&(node->concur), 1);
  }
  
  // 重置狀態(tài)
  thd->id = 0;
}

關(guān)閉時(shí):

關(guān)閉服務(wù)時(shí),釋放限流規(guī)則占用的內(nèi)存資源(遍歷規(guī)則鏈表,釋放其中每一個(gè)節(jié)點(diǎn)占用的內(nèi)存)。

void clean_up()
{
  cleanup();
}
  • 限流匹配

SQL限流的基本功能的實(shí)現(xiàn)邏輯為查詢串與規(guī)則串的匹配,匹配主要的策略如下:

根據(jù)DB判斷是否是對(duì)系統(tǒng)表的查詢,如果是對(duì)系統(tǒng)表的查詢,不做限流。

/* The flow control does not take effect on system tables */
  if (check_system_table(first_table->db)) {
    return ret;
  }

針對(duì)不同的操作類型,在相應(yīng)的限流規(guī)則鏈表上做模式匹配。

  • 獲取并解析鏈表上的節(jié)點(diǎn),根據(jù)鏈表節(jié)點(diǎn)中保存的關(guān)鍵字串與查詢串匹配;
  • 如果關(guān)鍵字串都匹配到,則匹配成功。
bool check_rule_matched(THD* thd, LIST* list)
{
  while (滿足條件,無異常) {
    // 根據(jù)大小寫開關(guān)是否打開,分別進(jìn)行模式串匹配
    it = find(query_str, item->key_array[nums]);
      
    // 如果it為空,沒有匹配到,查看下一個(gè)list,否則繼續(xù)匹配當(dāng)前限流規(guī)則節(jié)點(diǎn)
    judge();
  }


  // 匹配成功,或者對(duì)下一個(gè)節(jié)點(diǎn)進(jìn)行匹配
}

在匹配過程中維護(hù)原子變量cur_concur、cur_reject、total_reject,分別表示當(dāng)前并發(fā)數(shù)、當(dāng)前限流次數(shù)、總的限流次數(shù),用以判斷是否需要進(jìn)行限流以及在系統(tǒng)運(yùn)行期間觀察SQL限流的執(zhí)行狀態(tài)。

  • 數(shù)據(jù)獲取

用戶輸入的限流規(guī)則保存在限流規(guī)則系統(tǒng)表中,在需要讀取物理表中的數(shù)據(jù)時(shí),需要打開表、讀取數(shù)據(jù)、關(guān)閉表。

通過創(chuàng)建限流規(guī)則表讀取類來控制對(duì)表的操作,類的定義如下:

class Du_table_access {
public:
  Du_table_access() : m_drop_thd_object(NULL) {}
  virtual ~Du_table_access() {}


  // 初始化打開表的環(huán)境、鎖表并且打開表
  bool init(THD **thd, TABLE **table, bool is_write);
  
  // 關(guān)閉表,清理環(huán)境
  bool deinit(THD *thd, TABLE *table, bool error, bool need_commit);
  
  // 設(shè)置打開表的策略
  void before_open(THD *thd);
  
  // 如果需要的話創(chuàng)建線程,大部分時(shí)候并不需要,因?yàn)槭謩?dòng)執(zhí)行讀取數(shù)據(jù)的時(shí)候已經(jīng)在線程中了
  THD *create_thd();
  
  // 如果手動(dòng)創(chuàng)建了 thd,則需要手動(dòng)清理
  void drop_thd(THD *thd);
};

讀取到的數(shù)據(jù)以節(jié)點(diǎn)的形式保存,并且掛在LIST中進(jìn)行管理。

限流規(guī)則表設(shè)計(jì)

  • 定義系統(tǒng)表保存限流規(guī)則,表格式如下:

圖片圖片

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;
  • 權(quán)限與格式控制

通過存儲(chǔ)過程實(shí)現(xiàn)權(quán)限與格式控制:

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 ;

性能設(shè)計(jì)

當(dāng)開關(guān)關(guān)閉時(shí),對(duì)于每一個(gè)查詢?cè)趦?nèi)核中執(zhí)行,增加了對(duì)開關(guān)是否打開的判斷的消耗,該操作對(duì)于整個(gè)語(yǔ)句的執(zhí)行來說影響較小,可以忽略。

當(dāng)開關(guān)打開時(shí),需要將查詢字符串與限流規(guī)則進(jìn)行匹配,整個(gè)過程是內(nèi)存操作,且根據(jù)類型將限流規(guī)則分為不同的鏈表,加快匹配速度,整個(gè)過程對(duì)性能的影響與限流規(guī)則的數(shù)量以及復(fù)雜度有關(guān)(注:加入SQL限流特性對(duì)系統(tǒng)有影響,影響程度與限流規(guī)則的數(shù)量和復(fù)雜度有關(guān),但實(shí)際使用場(chǎng)景是針對(duì)少部分業(yè)務(wù)進(jìn)行限流,且不需要限流的時(shí)候不啟用該功能,因此該場(chǎng)景對(duì)性能的影響不決定最終實(shí)現(xiàn))。

性能設(shè)計(jì):

  • 刷新限流規(guī)則到節(jié)點(diǎn)時(shí),為了提升加載效率,節(jié)省不必要的遍歷,使用MySQL原生的鏈表插入方法,且只增刪限流規(guī)則,不允許修改限流規(guī)則。具體流程為,在限流規(guī)則節(jié)點(diǎn)增加ID字段,該字段與規(guī)則表中的自增主鍵ID對(duì)應(yīng),即該字段遞增。在從系統(tǒng)表中讀取數(shù)據(jù)后,根據(jù)ID可以快速判斷出該條記錄該插入的情況,此時(shí)對(duì)于該條記錄,可能有兩種場(chǎng)景:一是該條記錄已經(jīng)加載并解析到內(nèi)存(鏈表中存在該節(jié)點(diǎn)),無需再次插入;二是這條記錄還沒有加載到內(nèi)存,找到對(duì)應(yīng)位置插入即可。
  • 在數(shù)據(jù)庫(kù)實(shí)例啟動(dòng)時(shí),從已有系統(tǒng)表中加載一次數(shù)據(jù),提升后續(xù)限流效率。
  • 使用方面:

由于分隔符的選擇決定了限流規(guī)則的不同形式,因此修改分隔符會(huì)導(dǎo)致限流規(guī)則全部重新加載解析一次,盡量不在業(yè)務(wù)高峰期修改分隔符。

SQL限流的性能取決于限流規(guī)則的數(shù)量、關(guān)鍵字?jǐn)?shù)量、查詢的單詞數(shù)量,因此在使用時(shí),應(yīng)盡量使用較為通用的限流規(guī)則。

功能限制

  • 當(dāng)SQL語(yǔ)句匹配多條限流規(guī)則時(shí),優(yōu)先生效最新添加的規(guī)則;
  • 在添加SQL限流規(guī)則之前,已經(jīng)開始執(zhí)行的SQL語(yǔ)句,不會(huì)被記入并發(fā)數(shù);
  • 存儲(chǔ)過程、觸發(fā)器、函數(shù)和對(duì)系統(tǒng)表的查詢不受SQL限流的限制;
  • 當(dāng)設(shè)置過多限流規(guī)則時(shí),對(duì)性能有一定影響。

四、總結(jié)

本文詳細(xì)描述了基于MySQL內(nèi)核的SQL限流功能的整體架構(gòu)、主要功能模塊等關(guān)鍵要素。SQL限流的設(shè)計(jì)與實(shí)現(xiàn)基于原生MySQL的執(zhí)行原理與字符串匹配規(guī)則實(shí)現(xiàn)。整體功能對(duì)原生MySQL嵌入修改較少,除了對(duì)是否進(jìn)行限流的判斷以外,其他功能以獨(dú)立模塊呈現(xiàn),安全可控。

責(zé)任編輯:武曉燕 來源: 得物技術(shù)
相關(guān)推薦

2016-11-16 09:52:39

Linux讀書筆記內(nèi)核

2021-11-24 08:55:38

代理網(wǎng)關(guān)Netty

2009-06-14 22:09:24

Java界面布局DSL

2009-06-29 10:34:34

VxWorks視頻采集系統(tǒng)

2019-04-01 17:43:21

Linux內(nèi)核網(wǎng)關(guān)設(shè)計(jì)

2022-09-13 15:33:48

KubeEdge邊緣計(jì)算容器

2021-06-01 06:59:58

運(yùn)維Jira設(shè)計(jì)

2024-01-03 08:30:54

Redis分布式項(xiàng)目

2023-11-09 08:14:07

時(shí)間窗口限流

2015-09-16 09:24:49

2018-04-23 12:41:21

云計(jì)算政務(wù)云平臺(tái)架構(gòu)

2011-06-10 17:10:32

Qt GUI 瀏覽器

2013-01-21 10:26:13

2017-03-15 15:45:33

MySQL存儲(chǔ)引擎設(shè)計(jì)與實(shí)現(xiàn)

2024-03-13 08:34:22

2021-12-14 15:35:33

Flink數(shù)據(jù)分析數(shù)據(jù)集成平臺(tái)

2023-08-04 13:34:00

人工智能深度學(xué)習(xí)

2024-11-05 15:02:41

2021-07-23 14:58:28

Nginx限流方案

2009-05-18 09:11:00

IPTV融合寬帶
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)