成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

基于MySQL內核的SQL限流設計與實現

數據庫 MySQL
本文詳細描述了基于MySQL內核的SQL限流功能的整體架構、主要功能模塊等關鍵要素。SQL限流的設計與實現基于原生MySQL的執行原理與字符串匹配規則實現。

一、引言

編寫目的

本文詳細描述了SQL限流特性的需求設計方案以及使用方式,開發、測試人員可根據本文實現功能的開發、測試,DBA可根據本文合理使用SQL限流功能。

需求概述

生產環境中可能出現由于業務量增長過快或者慢SQL等原因導致CPU使用率打滿,當CPU打滿時,會影響所有依賴該數據庫實例的業務,因此需要有手段限制影響CPU的業務執行,保證其他核心業務不受影響。

SQL限流的目標是在出現CPU使用率打滿影響所有業務時,通過限制非核心業務或者慢SQL的業務,實現核心業務的快速恢復。

軟件結構

MySQL軟件結構如下圖所示:

圖片圖片

參考資料

MySQL官網:https://dev.mysql.com/doc/refman/5.7/en/

二、概要設計

架構設計

圖片圖片

總體架構如圖所示,SQL限流的主要功能在執行器工作階段通過限流規則與查詢串的匹配來實現。

流程圖

圖片圖片

三、詳細設計

功能設計

對外接口

針對SQL限流功能設計對外提供管理命令,如下:

  • 開關控制命令(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);
}

功能模塊詳細設計

  • 規則管理

SQL限流使用的場景為CPU負載過高,為了防止加重系統的負擔,限流規則應該事先加載到內存中。基于此,需要對內存中的限流規則進行管理,涉及的操作有:規則的讀取、移除、解析。

讀取

規則讀取的場景有:

  • 主動執行自定義讀取命令,用于更新限流規則到內存。每當添加限流規則后,需手動執行該操作,更新限流規則到內存。
  • 修改分隔符時。修改分隔符后,限流規則需要重新解析,因此也需要重新讀取。
  • 數據庫實例啟動時。基于性能考慮,在實例啟動時,將限流規則加載到內存中。

移除

規則移除的場景有:

  • 系統停止時移除限流規則時。
  • 手動刪除限流規則時。

解析

用戶輸入的規則在物理表中的表現是一個字符串,在將其加載到內存時,需要根據限流規則的分隔符將其解析為對應的規則模式串,在模式串中包含的關鍵字全部被滿足時,需要進行限流。解析過程如下:

  • 將物理表中的限流規則字符串讀取到內存字符串中。
  • 根據分隔符將字符串解析為關鍵字組成的模式串鏈表。
  • 流程控制

SQL限流的的流程控制添加在SQL執行階段,主要的內容有:

啟動時:

  • 加載、解析限流規則到內存中。
  • 解析預留用戶。
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();
}
  • 限流匹配

SQL限流的基本功能的實現邏輯為查詢串與規則串的匹配,匹配主要的策略如下:

根據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);
};

讀取到的數據以節點的形式保存,并且掛在LIST中進行管理。

限流規則表設計

  • 定義系統表保存限流規則,表格式如下:

圖片圖片

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 ;

性能設計

當開關關閉時,對于每一個查詢在內核中執行,增加了對開關是否打開的判斷的消耗,該操作對于整個語句的執行來說影響較小,可以忽略。

當開關打開時,需要將查詢字符串與限流規則進行匹配,整個過程是內存操作,且根據類型將限流規則分為不同的鏈表,加快匹配速度,整個過程對性能的影響與限流規則的數量以及復雜度有關(注:加入SQL限流特性對系統有影響,影響程度與限流規則的數量和復雜度有關,但實際使用場景是針對少部分業務進行限流,且不需要限流的時候不啟用該功能,因此該場景對性能的影響不決定最終實現)。

性能設計:

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

由于分隔符的選擇決定了限流規則的不同形式,因此修改分隔符會導致限流規則全部重新加載解析一次,盡量不在業務高峰期修改分隔符。

SQL限流的性能取決于限流規則的數量、關鍵字數量、查詢的單詞數量,因此在使用時,應盡量使用較為通用的限流規則。

功能限制

  • 當SQL語句匹配多條限流規則時,優先生效最新添加的規則;
  • 在添加SQL限流規則之前,已經開始執行的SQL語句,不會被記入并發數;
  • 存儲過程、觸發器、函數和對系統表的查詢不受SQL限流的限制;
  • 當設置過多限流規則時,對性能有一定影響。

四、總結

本文詳細描述了基于MySQL內核的SQL限流功能的整體架構、主要功能模塊等關鍵要素。SQL限流的設計與實現基于原生MySQL的執行原理與字符串匹配規則實現。整體功能對原生MySQL嵌入修改較少,除了對是否進行限流的判斷以外,其他功能以獨立模塊呈現,安全可控。

責任編輯:武曉燕 來源: 得物技術
相關推薦

2016-11-16 09:52:39

Linux讀書筆記內核

2021-11-24 08:55:38

代理網關Netty

2009-06-14 22:09:24

Java界面布局DSL

2009-06-29 10:34:34

VxWorks視頻采集系統

2019-04-01 17:43:21

Linux內核網關設計

2022-09-13 15:33:48

KubeEdge邊緣計算容器

2021-06-01 06:59:58

運維Jira設計

2024-01-03 08:30:54

Redis分布式項目

2023-11-09 08:14:07

時間窗口限流

2018-04-23 12:41:21

云計算政務云平臺架構

2015-09-16 09:24:49

2013-01-21 10:26:13

2011-06-10 17:10:32

Qt GUI 瀏覽器

2024-03-13 08:34:22

2017-03-15 15:45:33

MySQL存儲引擎設計與實現

2021-12-14 15:35:33

Flink數據分析數據集成平臺

2023-08-04 13:34:00

人工智能深度學習

2021-07-23 14:58:28

Nginx限流方案

2024-11-05 15:02:41

2009-05-18 09:11:00

IPTV融合寬帶
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品亚洲一区 | 少妇淫片aaaaa毛片叫床爽 | 国产精品久久久久久福利一牛影视 | 免费观看一级毛片 | 日本免费一区二区三区 | 日韩成人在线观看 | 成人免费观看男女羞羞视频 | 久草.com | 欧美专区日韩专区 | 日本免费黄色 | 欧美高清成人 | 成人免费淫片aa视频免费 | 亚洲国产欧美91 | 春色av| av中文字幕在线观看 | 久久精品视频网站 | av一级| 日韩精品在线一区 | 亚洲免费观看视频网站 | 婷婷久久综合 | 黑人巨大精品欧美一区二区免费 | 欧美日韩视频一区二区 | 久久久精品网站 | 日韩在线一区二区 | 婷婷丁香激情 | 国产一区二区三区免费视频 | 91极品视频| 色黄视频在线 | 国产免费拔擦拔擦8x高清 | 成人黄色电影在线观看 | 成人在线观看免费 | 欧美激情国产日韩精品一区18 | 男女网站在线观看 | 亚洲精品自拍 | 日本一区二区三区视频在线 | 国产精品视频一二三区 | 日韩一区二区黄色片 | 成人 在线| 成人黄色在线 | 欧美亚洲国产精品 | 国产精品一区在线 |