中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何運用LIST和RANGE與HASH分區解決熱點數據的分散

發布時間:2021-09-14 09:56:22 來源:億速云 閱讀:189 作者:柒染 欄目:大數據

本篇文章為大家展示了如何運用LIST和RANGE與HASH分區解決熱點數據的分散,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

熱點數據通俗的講是指被高頻使用到的數據,比如某些熱點事件,由于網絡的發酵效應,短時間能夠達到幾十萬甚至上百萬的并發量,針對這類場景,我們需要分析系統瓶頸所在,以及應對的技術實現

方案講解
  • 大并發架構演進
    如何運用LIST和RANGE與HASH分區解決熱點數據的分散
    1、圖1和圖2的區別是中間會有一層web緩存服務器,該服務它可以由nginx+lua+redis進行設計完成,緩存層的熱點數據分散,將會在后續的‘高并發度’章節做介紹。
    2、熱點數據肯定能在web層的緩存服務器被攔截住,防止把大量的請求打到應用服務器,但是對于非熱點的數據穿透緩存后會請求至DB,這部分數據每秒幾千的QPS對DB造成的壓力也是非常大的,這個時候我們需要一定的方案,保證請求的時效性,就是如何降低DB層面的IO次數

  • 場景分類
    熱點數據并發分為讀和寫兩種場景,日常高并發遇到的大多數都是讀場景,無論是采用何種的架構設計,都需要在緩存層和DB層面做熱點數據的分散,本章著重介紹后者

  • 原理分析
    大家都知道對熱點數據分散后,系統的性能會有顯著提升,是什么原理導致的,接下來我們探討一下db存儲的一些關鍵知識,上面兩個是大家經常用到的兩種mysql存儲引擎,尤其是后者,基本上筆者在工作中遇到的絕大多數的表都定義成了innodb引擎,兩者的差異在哪里?使用場景的區別在什么地方?
    1、讀數據
    myisam:與innodb一樣都采用BTREE實現,myisam是非聚集索引,索引文件和數據文件分離,它對讀的效率非常好,為什么呢,是因為它的存儲結構決定的,數據順序存儲,樹的葉子節點指向的是文件物理地址,所以查詢起來效率較高
    innodb:它是通過聚集索引實現,按照主鍵聚集,所以innodb引擎必須要擁有一個唯一標識這列數據的標識,對于聚集索引它的葉子節點存放的是數據,對于innodb的輔助索引它的葉子節點是主鍵的值,所以查詢的時候增加了二次查找,為了避免這種情況,可以直接使用聚集索引去查,但是現實情況是大多數的業務場景我們依然需要借助于輔助索引
    2、寫數據
    myisam:不支持事物,且寫優先級高于讀優先級,多線程讀可并發,讀和插入通過優化參數可并發,讀和更新不可并發,鎖的級別是表級別鎖
    innodb:支持事物,可以實現讀寫并發,行級別鎖,寫性能優于myisam的引擎
    3、數據頁
    是innodb數據存儲的一個基本單位,可以通過優化innodb_page_size參數進行修改,默認是16K,根據上面提到的聚集索引的原理,索引的大小、單條數據的大小決定了該數據頁所能包含的記錄條數,包含的數據記錄越多,需要做翻頁的幾率就越小,進行IO的次數相對就會減小

實現方式
  • 垂直分表
    垂直分表是對列做拆解,可以根據業務功能或者冷熱去拆解,比如對用戶表根據使用冷熱場景進行拆解的示意圖如下:
    如何運用LIST和RANGE與HASH分區解決熱點數據的分散
    垂直分表的意義是在于將熱表進一步拆分,降低數據表的因為單行長度過大,導致的多頁查詢,引起的IO過多問題

  • 水平分表
    水平分表是對行做拆解,拆完以后單張表的數據量會更小
    比如對5000萬的數據量,做水平分表,原來單表5000萬的數據記錄,拆分為10張表以后,每張表則為500萬記錄
    每個索引頁的大小固定默認16K,所以在單頁大小固定的情況下,單表記錄越多,索引頁的頁數越多,查詢期間分頁的概率和頻次就會增加
    水平分表就是解決這個問題,分表的實現方式:分區、分表/分庫,具體參考下面的介紹。

  • 最佳實踐
    1、冷熱數據分離
    以文章內容系統為例:標題、作者、分類、創建時間、點贊數、回復數、最近回復時間
    1.1、冷數據:可以理解成偏靜態的數據,會頻繁的被讀取,但是幾乎或者很少被改變,這類數據對讀的性能要求較高,數據存儲可以使用myisam引擎
    1.2、熱數據:數據內容被頻繁改變,這類數據對并發讀寫要求較高,我們可以使用innodb引擎存儲
    根據具體的使用場景使用不同的存儲引擎,以達到性能的相對最優,將文章內容系統的表結構進行冷熱拆分,拆分后的表結構如下:
    如何運用LIST和RANGE與HASH分區解決熱點數據的分散
    1.3、拆分前后性能比對
    插入100000條數據,對拆分前后的文章表做查詢,性能比對的趨勢如下,同樣都是模擬50個并發,一共2500次請求,每個線程50個請求,采用ID隨機,這樣更貼近真實的查詢場景,很明顯拆分后的效果更勝一籌:
    拆分后單表測試:

    mysqlslap -h227.0.0.1 -uroot -P3306 -p --concurrency=50 --iterations=1    --engine=myisam --number-of-queries=2500 --query='select * from cms_blog_static where id=RAND()*1000000' --create-schema=test

    如何運用LIST和RANGE與HASH分區解決熱點數據的分散
    未拆分測試:

    mysqlslap -h227.0.0.1 -uroot -P3306 -p --concurrency=50 --iterations=1    --engine=innodb --number-of-queries=2500 --query='select * from cms_blog where id=RAND()*1000000' --create-schema=test

    如何運用LIST和RANGE與HASH分區解決熱點數據的分散
    2、減少單行數據大小
    對于拆分以后的數據表,我們能否進一步降低單行數據的大小呢,總結起來常用的方法如下:
    2.1、設置合理的字段長度
    大家都知道不同的字段類型占用的存儲空間不同,如下圖:

    類型長度(字節)定長/非定長
    TINYINT1定長
    SMALLINT2定長 
    MEDIUMINT3定長
    INT4定長
    BIGINT8定長
    FLOAT(m)4字節(m<=24)、8字節(m>=24 and m<=53)非定長
    FLOAT4定長
    DOUBLE8定長
    DOUBLE PRECISION8定長
    DECIMAL(m,d)m字節(m>d)、d+2字節(m<d)非定長
    NUMBER(m,d)m字節(m>d)、d+2字節(m<d)非定長
    DATE3定長
    DATETIME8定長
    TIMESTAMP4定長
    TIME3定長
    YEAR1定長
    CHAR(m)m非定長
    VARCHAR(m)l字節,l就是實際存儲字節(l<=m)非定長
    BLOB, TEXTl+2字節,l就是實際存儲字節非定長
    LONGBLOB, LONGTEXTl+4字節,l就是實際存儲字節非定長

    我們在實際使用中,需要根據實際的需要選擇合理的類型,能有效的減小單行數據的大小,比如,user_status,一般我們定義成tinyint(1)即可,沒必要定義成int,白白多占用3個字節
    2.2、設置合理的索引長度
    2.2.1、對于需要建索引的字段,如果字段占用的空間越大,對于索引來說,建立索引的長度就越長,索引頁大小不變的情況下,數據條數就越少,查詢需要做IO的次數就越頻繁
    2.2.2、對于某些索引字段,如果我們可以通過前綴字段能達到很好的區分度,則可以控制創建索引的長度,目的是索引頁的含的數據行數更多,減少IO,方式如下:

    //如下,我們根據字段1和字段2,指定的組合索引的長度
    alter table table_name add index index_name (field1(length2),field2(length3))

    2.2.3、索引的選擇性
    索引本身是由開銷的,首先是存儲資源,然后插入和更新帶來的對B+Tree樹的維護,數據更新帶來的性能下降,所以對于我們的原則是:索引該不該建,以及用什么字段建
    數據量少-則不建,區分度或者選擇性不高-則不建,數據量少大家很容易理解,小于1W條數據全表掃描也能接收,選擇性或者區分度是指,數據的分散程度,比如某個用戶表,有一個性別字段,數據量越大它的索引選擇性越差,計算公式如下:

    //返回值范圍(0,1],該值越大,索引選擇性越高
    select distinct(col)/count(*) from table_name

    同理,對于需要控制索引長度的字段,計算選擇性如下:

    select distinct(left(col,n))/count(*) from table_name

    2.2.4、性能比較
    通過對100w的數據,對數據行大小做優化,前后性能比對結果如下:
    優化前后的表結構定義如下:

    --優化前
    CREATE TABLE `cms_blog` (
      `id` bigint(20) NOT NULL auto_increment,
      `title` varchar(60) NOT NULL,
      `creator` varchar(20) NOT NULL,
      `blog_type` tinyint(1) not NULL,
      `reply_praise` int(10) UNSIGNED,
      `reply_count` int(10) UNSIGNED,
      `create_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
      `update_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
      PRIMARY KEY (`id`)
    ) ENGINE=innodb DEFAULT CHARSET=utf8;
    --創建索引
    alter table cms_blog add index idx_reply_count (reply_count);
    --優化后reply_praise和reply_count
    CREATE TABLE `cms_blog_v2` (
      `id` bigint(20) NOT NULL auto_increment,
      `title` varchar(60) NOT NULL,
      `creator` varchar(20) NOT NULL,
      `blog_type` tinyint(1) not NULL,
      `reply_praise` MEDIUMINT(10) UNSIGNED,
      `reply_count` MEDIUMINT(10) UNSIGNED,
      `create_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
      `update_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
      PRIMARY KEY (`id`)
    ) ENGINE=innodb DEFAULT CHARSET=utf8;
    --創建索引
    alter table cms_blog_v2 add index idx_reply_count (reply_count);

    壓測腳本如下:

    --壓測腳本,舊表
    mysqlslap -h227.0.0.1 -uroot -P3306 -p --concurrency=50 --iterations=1    --engine=innodb --number-of-queries=2500 --query='select * from cms_blog where reply_count>999990' --create-schema=test
    --壓測腳本,新表
    mysqlslap -h227.0.0.1 -uroot -P3306 -p --concurrency=50 --iterations=1    --engine=innodb --number-of-queries=2500 --query='select * from cms_blog_v2  where reply_count>999990' --create-schema=test

    性能表現,舊表和新表壓測表現如下:
    如何運用LIST和RANGE與HASH分區解決熱點數據的分散
    新表優化后性能明顯有提升:
    如何運用LIST和RANGE與HASH分區解決熱點數據的分散
    2.3、主鍵的選擇
    盡量使用保持單調性的自增主鍵,避免使用uuid、hash方式、業務自定義主鍵,減少索引重建對性能的影響
    3、分散數據頁查詢
    3.1、數據分區
    數據分區可以有效的提升查詢的性能,充分利用不同分區所關聯的IO存儲,在邏輯上是屬于同一張表,物理上可以分散到不同的磁盤存儲,缺點是跨分區查詢的性能稍差,所以互聯網公司在實際當中很少用到數據分區,一般建議物理分表的方式實現

  • CREATE TABLE table_name (
      id INT AUTO_INCREMENT,
      customer_surname VARCHAR(30),
      store_id INT,
      salesperson_id INT,
      order_date DATE,
      note VARCHAR(500),
      INDEX idx (id)
    ) ENGINE = INNODB
      PARTITION BY LIST(store_id) (
      PARTITION p1
      VALUES IN (1, 3, 4, 17)
      INDEX DIRECTORY = '/var/path3'
      DATA DIRECTORY = '/var/path2';

    3.1.1、分區方式
    3.1.1.1、RANGE partitioning

    CREATE TABLE employees (
        id INT NOT NULL,
        fname VARCHAR(30),
        lname VARCHAR(30),
        hired DATE NOT NULL DEFAULT '1970-01-01',
        separated DATE NOT NULL DEFAULT '9999-12-31',
        job_code INT NOT NULL,
        store_id INT NOT NULL
    )
    PARTITION BY RANGE (store_id) (
        PARTITION p0 VALUES LESS THAN (6),
        PARTITION p1 VALUES LESS THAN (11),
        PARTITION p2 VALUES LESS THAN (16),
        PARTITION p3 VALUES LESS THAN (21)
    );

    3.1.1.2、LIST Partitioning

    CREATE TABLE employees (
        id INT NOT NULL,
        fname VARCHAR(30),
        lname VARCHAR(30),
        hired DATE NOT NULL DEFAULT '1970-01-01',
        separated DATE NOT NULL DEFAULT '9999-12-31',
        job_code INT,
        store_id INT
    )
    PARTITION BY LIST(store_id) (
        PARTITION pNorth VALUES IN (3,5,6,9,17),
        PARTITION pEast VALUES IN (1,2,10,11,19,20),
        PARTITION pWest VALUES IN (4,12,13,14,18),
        PARTITION pCentral VALUES IN (7,8,15,16)
    );

    3.1.1.3、COLUMNS Partitioning

    --range columns
    CREATE TABLE rc1 (
        a INT,
        b INT
    )
    PARTITION BY RANGE COLUMNS(a, b) (
        PARTITION p0 VALUES LESS THAN (5, 12),
        PARTITION p3 VALUES LESS THAN (MAXVALUE, MAXVALUE)
    );
    --list columns
    CREATE TABLE customers_1 (
        first_name VARCHAR(25),
        last_name VARCHAR(25),
        street_1 VARCHAR(30),
        street_2 VARCHAR(30),
        city VARCHAR(15),
        renewal DATE
    )
    PARTITION BY LIST COLUMNS(city) (
        PARTITION pRegion_1 VALUES IN('Oskarshamn', 'H?gsby', 'M?nster?s'),
        PARTITION pRegion_2 VALUES IN('Vimmerby', 'Hultsfred', 'V?stervik'),
        PARTITION pRegion_3 VALUES IN('N?ssj?', 'Eksj?', 'Vetlanda'),
        PARTITION pRegion_4 VALUES IN('Uppvidinge', 'Alvesta', 'V?xjo')
    );

    3.1.1.4、HASH Partitioning

    CREATE TABLE employees (
        id INT NOT NULL,
        fname VARCHAR(30),
        lname VARCHAR(30),
        hired DATE NOT NULL DEFAULT '1970-01-01',
        separated DATE NOT NULL DEFAULT '9999-12-31',
        job_code INT,
        store_id INT
    )
    PARTITION BY HASH(store_id)
    PARTITIONS 4;

    3.1.1.5、KEY Partitioning

    CREATE TABLE tk (
        col1 INT NOT NULL,
        col2 CHAR(5),
        col3 DATE
    )
    PARTITION BY LINEAR KEY (col1)
    PARTITIONS 3;

    3.2、數據分表/分庫
    數據分表解決的問題,提升單表的并發能力,文件分布在不同的表文件,對IO性能進一步提升,另外對讀寫鎖影響的數據量變少,插入數據需要做索引重建的數據減少,insert或update性能會更好
    3.2.1、分表和分庫方式
    3.2.1.1:哈希取模方式,hash(關鍵字)%N
    3.2.1.2:按照時間,如按照年或者月分表
    3.2.1.3、按照業務,以訂單業務為例,平臺訂單、三方訂單
    3.2.2、分庫分表中間件
    整體來說分為在客戶端實現,和代理端實現,比如:cobar、sharding-jdbc、mycat等,具體使用可以自行檢索

上述內容就是如何運用LIST和RANGE與HASH分區解決熱點數據的分散,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

易门县| 西乡县| 会宁县| 诸暨市| 安宁市| 台江县| 独山县| 丁青县| 常宁市| 南漳县| 绩溪县| 塔城市| 龙口市| 东阳市| 凯里市| 肥城市| 临海市| 乌苏市| 沙河市| 宜宾市| 苍南县| 贞丰县| 平安县| 北京市| 合川市| 区。| 铜陵市| 全州县| 绥芬河市| 诸暨市| 平泉县| 灌云县| 界首市| 东阳市| 紫云| 朝阳区| 永德县| 安化县| 泰和县| 阿克苏市| 浪卡子县|