中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

簡(jiǎn)單網(wǎng)站建設(shè)模板下載百度關(guān)鍵詞怎么做排名

簡(jiǎn)單網(wǎng)站建設(shè)模板下載,百度關(guān)鍵詞怎么做排名,h5響應(yīng)式網(wǎng)站模板制作,wordpress替換圖片不顯示讀寫分離 什么時(shí)候需要讀寫分離 互聯(lián)網(wǎng)大部分業(yè)務(wù)場(chǎng)景都是讀多寫少的,讀和寫的請(qǐng)求對(duì)比可能差了不止一個(gè)數(shù)量級(jí)。為了不讓數(shù)據(jù)庫的讀成為業(yè)務(wù)瓶頸,同時(shí)也為了保證寫庫的成功率,一般會(huì)采用讀寫分離的技術(shù)來保證。 讀寫分離的實(shí)現(xiàn)是把訪問的壓…

讀寫分離

什么時(shí)候需要讀寫分離

互聯(lián)網(wǎng)大部分業(yè)務(wù)場(chǎng)景都是讀多寫少的,讀和寫的請(qǐng)求對(duì)比可能差了不止一個(gè)數(shù)量級(jí)。為了不讓數(shù)據(jù)庫的讀成為業(yè)務(wù)瓶頸,同時(shí)也為了保證寫庫的成功率,一般會(huì)采用讀寫分離的技術(shù)來保證。
讀寫分離的實(shí)現(xiàn)是把訪問的壓力從主庫轉(zhuǎn)移到從庫。分離讀庫和寫庫操作,從 CRUD 的角度,主數(shù)據(jù)庫處理新增、修改、刪除等事務(wù)性操作,從數(shù)據(jù)庫處理 SELECT 查詢操作。實(shí)現(xiàn)上,可以有一主一從,一個(gè)主庫配置一個(gè)從庫;也可以一主多從,一個(gè)主庫配置多個(gè)從庫,讀操作通過多個(gè)從庫進(jìn)行,支撐更高的讀并發(fā)壓力。

MySQL 主從復(fù)制技術(shù)

binlog 日志

MySQL InnoDB 引擎的主從復(fù)制,是通過二進(jìn)制日志 binlog 來實(shí)現(xiàn)。除了數(shù)據(jù)查詢語句 select 以外,binlog 日志記錄了其他各類數(shù)據(jù)寫入操作,包括 DDL 和 DML 語句。

binlog 有三種格式:Statement、Row 及 Mixed。

  • Statement 格式,基于 SQL 語句的復(fù)制。binlog 會(huì)記錄每一條修改數(shù)據(jù)的 SQL 操作,從庫拿到后在本地進(jìn)行回放就可以了。

  • Row 格式,基于行信息復(fù)制。以行為維度,記錄每一行數(shù)據(jù)修改的細(xì)節(jié),不記錄執(zhí)行 SQL 語句的上下文相關(guān)的信息,僅記錄行數(shù)據(jù)的修改。假設(shè)有一個(gè)批量更新操作,會(huì)以行記錄的形式來保存二進(jìn)制文件,這樣可能會(huì)產(chǎn)生大量的日志內(nèi)容。

  • Mixed 格式,混合模式復(fù)制。是 Statement 與 Row 的結(jié)合,在這種方式下,不同的 SQL 操作會(huì)區(qū)別對(duì)待。比如一般的數(shù)據(jù)操作使用 row 格式保存,有些表結(jié)構(gòu)的變更語句,使用 statement 來記錄。

主從復(fù)制過程

  • 主庫將變更寫入 binlog 日志,從庫連接到主庫之后,主庫會(huì)創(chuàng)建一個(gè)log dump 線程,用于發(fā)送 bin log 的內(nèi)容。
  • 從庫開啟同步以后,會(huì)創(chuàng)建一個(gè) IO 線程用來連接主庫,請(qǐng)求主庫中更新的 bin log,I/O 線程接收到主庫 binlog dump 進(jìn)程發(fā)來的更新之后,保存在本地 relay 日志中。
  • 接著從庫中有一個(gè) SQL 線程負(fù)責(zé)讀取 relay log 中的內(nèi)容,同步到數(shù)據(jù)庫存儲(chǔ)中,也就是在自己本地進(jìn)行回放,最終保證主從數(shù)據(jù)的一致性。
    在這里插入圖片描述

讀寫分離要注意的問題

主從復(fù)制下的延時(shí)問題

主庫和從庫是兩個(gè)不同的數(shù)據(jù)源,主從復(fù)制過程會(huì)存在一個(gè)延時(shí)。當(dāng)主庫有數(shù)據(jù)寫入之后,同時(shí)寫入 binlog 日志文件中,然后從庫通過 binlog 文件同步數(shù)據(jù),額外執(zhí)行日志同步和寫入操作會(huì)有一定時(shí)間的延遲。特別是在高并發(fā)場(chǎng)景下,剛寫入主庫的數(shù)據(jù)是不能馬上在從庫讀取的,要等待幾十毫秒或者上百毫秒以后才可以。

在某些對(duì)一致性要求較高的業(yè)務(wù)場(chǎng)景中,這種主從導(dǎo)致的延遲會(huì)引起一些業(yè)務(wù)問題,比如訂單支付,付款已經(jīng)完成,主庫數(shù)據(jù)更新了,從庫還沒有,這時(shí)候去從庫讀數(shù)據(jù),會(huì)出現(xiàn)訂單未支付的情況,在業(yè)務(wù)中是不能接受的。

解決方法

  • 敏感業(yè)務(wù)強(qiáng)制讀主庫。業(yè)務(wù)需要寫庫后實(shí)時(shí)讀數(shù)據(jù)的可以通過強(qiáng)制讀主庫來解決。
  • 關(guān)鍵業(yè)務(wù)不進(jìn)行讀寫分離。對(duì)一致性不敏感的業(yè)務(wù)可以進(jìn)行讀寫分離(電商中的訂單評(píng)論、個(gè)人信息等)。對(duì)一致性要求比較高的業(yè)務(wù)不進(jìn)行讀寫分離,避免延遲導(dǎo)致的問題(比如金融支付)。

主從復(fù)制如何避免丟數(shù)據(jù)

假設(shè)在數(shù)據(jù)庫主從同步時(shí),主庫宕機(jī),并且數(shù)據(jù)還沒有同步到從庫,就會(huì)出現(xiàn)數(shù)據(jù)丟失和不一致的情況。

MySQL 數(shù)據(jù)庫主從復(fù)制有異步復(fù)制、半同步復(fù)制和全同步復(fù)制的方式。

  • 異步復(fù)制。主庫在接受并處理客戶端的寫入請(qǐng)求時(shí),直接返回執(zhí)行結(jié)果,不關(guān)心從庫同步是否成功,這樣就會(huì)存在上面說的問題,主庫崩潰以后,可能有部分操作沒有同步到從庫,出現(xiàn)數(shù)據(jù)丟失問題。
  • 半同步復(fù)制。主庫需要等待至少一個(gè)從庫完成同步之后,才完成寫操作。主庫在執(zhí)行完客戶端提交的事務(wù)后,從庫將日志寫入自己本地的 relay log 之后,會(huì)返回一個(gè)響應(yīng)結(jié)果給主庫,主庫確認(rèn)從庫已經(jīng)同步完成,才會(huì)結(jié)束本次寫操作。相對(duì)于異步復(fù)制,半同步復(fù)制提高了數(shù)據(jù)的安全性,避免了主庫崩潰出現(xiàn)的數(shù)據(jù)丟失,但是同時(shí)也增加了主庫寫操作的耗時(shí)。
  • 全同步復(fù)制。是在多從庫的情況下,當(dāng)主庫執(zhí)行完一個(gè)事務(wù),需要等待所有的從庫都同步完成以后,才完成本次寫操作。全同步復(fù)制需要等待所有從庫執(zhí)行完對(duì)應(yīng)的事務(wù),所以整體性能是最差的。

分庫分表

背景

數(shù)據(jù)規(guī)模飛速增長,傳統(tǒng)的單庫單表架構(gòu)不足以支撐業(yè)務(wù)發(fā)展,存在性能瓶頸。

讀寫的數(shù)據(jù)量限制

數(shù)據(jù)庫的數(shù)據(jù)量增大會(huì)直接影響讀寫的性能,比如一次查詢操作,掃描 5 萬條數(shù)據(jù)和 500 萬條數(shù)據(jù),查詢速度肯定是不同的。

MySQL 單庫和單表的數(shù)據(jù)量限制,和不同的服務(wù)器配置,以及不同結(jié)構(gòu)的數(shù)據(jù)存儲(chǔ)有關(guān),并沒有一個(gè)確切的數(shù)字。這里參考阿里巴巴的《Java 開發(fā)手冊(cè)》中數(shù)據(jù)庫部分的建表規(guī)約:

單表行數(shù)超過 500 萬行或者單表容量超過 2GB,才推薦進(jìn)行分庫分表。

避免過度設(shè)計(jì)。分庫分表雖然可以提高性能,但盲目地進(jìn)行分庫分表只會(huì)增加系統(tǒng)的復(fù)雜度。

數(shù)據(jù)庫連接限制

數(shù)據(jù)庫的連接是有限制的,不能無限制創(chuàng)建,比如 MySQL 中可以使用 max_connections 查看默認(rèn)的最大連接數(shù),當(dāng)訪問連接數(shù)過多時(shí),就會(huì)導(dǎo)致連接失敗。以電商為例,假設(shè)存儲(chǔ)沒有進(jìn)行分庫,用戶、商品、訂單和交易,所有的業(yè)務(wù)請(qǐng)求都訪問同一個(gè)數(shù)據(jù)庫,產(chǎn)生的連接數(shù)是非常可觀的,可能導(dǎo)致數(shù)據(jù)庫無法支持業(yè)務(wù)請(qǐng)求。
如果不進(jìn)行數(shù)據(jù)庫拆分,大量數(shù)據(jù)訪問都集中在單臺(tái)機(jī)器上,對(duì)磁盤 IO、CPU 負(fù)載等都會(huì)產(chǎn)生很大的壓力,并且直接影響業(yè)務(wù)操作的性能。

分庫分表原理

垂直切分

一般是按照業(yè)務(wù)和功能的維度進(jìn)行拆分,把數(shù)據(jù)分別放到不同的數(shù)據(jù)庫中。
在這里插入圖片描述
垂直分庫
針對(duì)的是一個(gè)系統(tǒng)中對(duì)不同的業(yè)務(wù)進(jìn)行拆分。
根據(jù)業(yè)務(wù)維度進(jìn)行數(shù)據(jù)的分離,剝離為多個(gè)數(shù)據(jù)庫。比如電商網(wǎng)站早期,商品數(shù)據(jù)、會(huì)員數(shù)據(jù)、訂單數(shù)據(jù)都是集中在一個(gè)數(shù)據(jù)庫中,隨著業(yè)務(wù)的發(fā)展,單庫處理能力已成為瓶頸,這個(gè)時(shí)候就需要進(jìn)行相關(guān)的優(yōu)化,進(jìn)行業(yè)務(wù)維度的拆分,分離出會(huì)員數(shù)據(jù)庫、商品數(shù)據(jù)庫和訂單數(shù)據(jù)庫等。

垂直分表
針對(duì)業(yè)務(wù)上的字段比較多的大表進(jìn)行的。
一般是把業(yè)務(wù)寬表中比較獨(dú)立的字段,或者不常用的字段拆分到單獨(dú)的數(shù)據(jù)表中。比如早期的商品表中,可能包含了商品信息、價(jià)格、庫存等,可以拆分出來價(jià)格擴(kuò)展表、庫存擴(kuò)展表等。

水平切分

在這里插入圖片描述
把相同的表結(jié)構(gòu)分散到不同的數(shù)據(jù)庫和不同的數(shù)據(jù)表中,避免訪問集中的單個(gè)數(shù)據(jù)庫或者單張數(shù)據(jù)表,具體的分庫和分表規(guī)則,一般是通過業(yè)務(wù)主鍵,進(jìn)行哈希取模操作。

例如,電商業(yè)務(wù)中的訂單信息訪問頻繁,可以將訂單表分散到多個(gè)數(shù)據(jù)庫中,實(shí)現(xiàn)分庫;在每個(gè)數(shù)據(jù)庫中,繼續(xù)進(jìn)行拆分到多個(gè)數(shù)據(jù)表中,實(shí)現(xiàn)分表。路由策略可以使用訂單 ID 或者用戶 ID,進(jìn)行取模運(yùn)算,路由到不同的數(shù)據(jù)庫和數(shù)據(jù)表中。

分庫分表后引入的問題

分布式事務(wù)問題

對(duì)業(yè)務(wù)進(jìn)行分庫之后,同一個(gè)操作會(huì)分散到多個(gè)數(shù)據(jù)庫中,涉及跨庫執(zhí)行 SQL 語句,也就出現(xiàn)了分布式事務(wù)問題。

比如數(shù)據(jù)庫拆分后,訂單和庫存在兩個(gè)庫中,一個(gè)下單減庫存的操作,就涉及跨庫事務(wù)??梢允褂梅植际绞聞?wù)中間件,實(shí)現(xiàn) TCC 等事務(wù)模型;也可以使用基于本地消息表的分布式事務(wù)實(shí)現(xiàn)。

跨庫關(guān)聯(lián)查詢問題

分庫分表后,跨庫和跨表的查詢操作實(shí)現(xiàn)起來會(huì)比較復(fù)雜,性能也無法保證。在實(shí)際開發(fā)中,針對(duì)這種需要跨庫訪問的業(yè)務(wù)場(chǎng)景,一般會(huì)使用額外的存儲(chǔ),比如維護(hù)一份文件索引。另一個(gè)方案是通過合理的數(shù)據(jù)庫字段冗余,避免出現(xiàn)跨庫查詢。

跨庫跨表的合并和排序問題

分庫分表以后,數(shù)據(jù)分散存儲(chǔ)到不同的數(shù)據(jù)庫和表中,如果查詢指定數(shù)據(jù)列表,或者需要對(duì)數(shù)據(jù)列表進(jìn)行排序時(shí),就變得異常復(fù)雜,則需要在內(nèi)存中進(jìn)行處理,整體性能會(huì)比較差,一般來說,會(huì)限制這類型的操作。

分庫分表中間件實(shí)現(xiàn)

業(yè)務(wù)中實(shí)現(xiàn)分庫分表,需要自己去實(shí)現(xiàn)路由規(guī)則,實(shí)現(xiàn)跨庫合并排序等操作,具有一定的開發(fā)成本,可以考慮使用開源的分庫分表中間件。這里比較推薦 Apache ShardingSphere,另外也可以參考淘寶的 TDDL 等。

ShardingSphere 的前身是當(dāng)當(dāng)開源的 Sharding-JDBC,目前更名為 ShardingSphere,并且已經(jīng)加入 Apache 基金會(huì)。ShardingSphere 在 Sharding-JDBC 的基礎(chǔ)上,額外提供了 Sharding-Proxy,以及正在規(guī)劃中的 Sharding-Sidecar。其中 Sharding-JDBC 用來實(shí)現(xiàn)分庫分表,另外也添加了對(duì)分布式事務(wù)等的支持。 ShardingSphere 的具體應(yīng)用《ShardingSphere 用戶手冊(cè)》。

TDDL(Taobao Distributed Data Layer)是淘寶團(tuán)隊(duì)開發(fā)的數(shù)據(jù)庫中間件,用于解決分庫分表場(chǎng)景下的訪問路由,TDDL 在淘寶大規(guī)模應(yīng)用 TDDL 項(xiàng)目

存儲(chǔ)拆分后,解決唯一主鍵問題

在單庫單表時(shí),業(yè)務(wù) ID 可以依賴數(shù)據(jù)庫的自增主鍵實(shí)現(xiàn),存儲(chǔ)拆分到了多處,如何解決主鍵。

生成主鍵方案

使用單獨(dú)的自增數(shù)據(jù)表。

存儲(chǔ)拆分以后,創(chuàng)建一張單點(diǎn)的數(shù)據(jù)表,比如現(xiàn)在需要生成訂單 ID,我們創(chuàng)建下面一張數(shù)據(jù)表:

CREATE TABLE IF NOT EXISTS `order_sequence`(`order_id` INT UNSIGNED AUTO_INCREMENT,PRIMARY KEY ( `order_id` ))ENGINE=InnoDB DEFAULT CHARSET=utf8;

當(dāng)每次需要生成唯一 ID 時(shí),就去對(duì)應(yīng)的這張數(shù)據(jù)表里新增一條記錄,使用返回的自增主鍵 ID 作為業(yè)務(wù) ID。

問題

  • 性能無法保證,在并發(fā)比較高的情況下,如果通過這樣的數(shù)據(jù)表來創(chuàng)建自增 ID,生成主鍵很容易成為性能瓶頸。
  • 存在單點(diǎn)故障,如果生成自增 ID 的數(shù)據(jù)庫掛掉,那么會(huì)直接影響創(chuàng)建功能。

使用 UUID 能否實(shí)現(xiàn)

生成一個(gè) UUID:

public String getUUID(){UUID uuid=UUID.randomUUID();return uuid.toString();}

問題:

  • UUID 作為數(shù)據(jù)庫主鍵太長了,會(huì)導(dǎo)致比較大的存儲(chǔ)開銷。
  • UUID 是無序的,如果使用 UUID 作為主鍵,會(huì)降低數(shù)據(jù)庫的寫入性能。

以 MySQL 為例,MySQL 建議使用自增 ID 作為主鍵,我們知道 MySQL InnoDB 引擎支持索引,底層數(shù)據(jù)結(jié)構(gòu)是 B+ 樹,如果主鍵為自增 ID 的話,那么 MySQL 可以按照磁盤的順序去寫入;如果主鍵是非自增 ID,在寫入時(shí)需要增加很多額外的數(shù)據(jù)移動(dòng),將每次插入的數(shù)據(jù)放到合適的位置上,導(dǎo)致出現(xiàn)頁分裂,降低數(shù)據(jù)寫入的性能。

基于 Snowflake 算法

Snowflake 是 Twitter 開源的分布式 ID 生成算法,由 64 位的二進(jìn)制數(shù)字組成,一共分為 4 部分.
在這里插入圖片描述

其中:

  • 第 1 位默認(rèn)不使用,作為符號(hào)位,總是 0,保證數(shù)值是正數(shù);
  • 41 位時(shí)間戳,表示毫秒數(shù),我們計(jì)算一下,41 位數(shù)字可以表示 241 毫秒,換算成年,結(jié)果是 69 年多一點(diǎn),一般來說,這個(gè)數(shù)字足夠在業(yè)務(wù)中使用了;
  • 10 位工作機(jī)器 ID,支持 210 也就是 1024 個(gè)節(jié)點(diǎn);
  • 12 位序列號(hào),作為當(dāng)前時(shí)間戳和機(jī)器下的流水號(hào),每個(gè)節(jié)點(diǎn)每毫秒內(nèi)支持 212 的區(qū)間,也就是 4096 個(gè) ID,換算成秒,相當(dāng)于可以允許 409 萬的 QPS,如果在這個(gè)區(qū)間內(nèi)超出了 4096,則等待至下一毫秒計(jì)算。

Twitter 給出了 Snowflake 算法的示例,具體實(shí)現(xiàn)應(yīng)用了大量的位運(yùn)算,可以點(diǎn)擊具體的代碼庫查看。

Snowflake 算法可以作為一個(gè)單獨(dú)的服務(wù),部署在多臺(tái)機(jī)器上,產(chǎn)生的 ID 是趨勢(shì)遞增的,不需要依賴數(shù)據(jù)庫等第三方系統(tǒng),并且性能非常高,理論上 409 萬的 QPS 是一個(gè)非??捎^的數(shù)字,可以滿足大部分業(yè)務(wù)場(chǎng)景,其中的機(jī)器 ID 部分,可以根據(jù)業(yè)務(wù)特點(diǎn)來分配,比較靈活。

不足

存在時(shí)鐘回?fù)軉栴}

服務(wù)器的本地時(shí)鐘并不是絕對(duì)準(zhǔn)確的,在一些業(yè)務(wù)場(chǎng)景中,比如在電商的整點(diǎn)搶購中,為了防止不同用戶訪問的服務(wù)器時(shí)間不同,則需要保持服務(wù)器時(shí)間的同步。為了確保時(shí)間準(zhǔn)確,會(huì)通過 NTP 的機(jī)制來進(jìn)行校對(duì),NTP(Network Time Protocol)指的是網(wǎng)絡(luò)時(shí)間協(xié)議,用來同步網(wǎng)絡(luò)中各個(gè)計(jì)算機(jī)的時(shí)間。

如果服務(wù)器在同步 NTP 時(shí)出現(xiàn)不一致,出現(xiàn)時(shí)鐘回?fù)?#xff0c;那么 SnowFlake 在計(jì)算中可能出現(xiàn)重復(fù) ID。除了 NTP 同步,閏秒也會(huì)導(dǎo)致服務(wù)器出現(xiàn)時(shí)鐘回?fù)?#xff0c;不過時(shí)鐘回?fù)苁切「怕适录?#xff0c;在并發(fā)比較低的情況下一般可以忽略。時(shí)鐘回?fù)軉栴},可以進(jìn)行延遲等待,直到服務(wù)器時(shí)間追上來為止。

數(shù)據(jù)庫維護(hù)區(qū)間分配

淘寶的 TDDL 等數(shù)據(jù)庫中間件使用的主鍵生成策略?;跀?shù)據(jù)庫維護(hù)自增ID區(qū)間,結(jié)合內(nèi)存分配的策略。

步驟

  • 首先在數(shù)據(jù)庫中創(chuàng)建 sequence 表,其中的每一行,用于記錄某個(gè)業(yè)務(wù)主鍵當(dāng)前已經(jīng)被占用的 ID 區(qū)間的最大值。

sequence 表的主要字段是 name 和 value,其中 name 是當(dāng)前業(yè)務(wù)序列的名稱,value 存儲(chǔ)已經(jīng)分配出去的 ID 最大值。

CREATE TABLE `sequence` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'Id',`name` varchar(64) NOT NULL COMMENT 'sequence name',`value` bigint(32) NOT NULL COMMENT 'sequence current value',PRIMARY KEY (`id`),UNIQUE KEY `unique_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
  • 接下來插入一條行記錄,當(dāng)需要獲取主鍵時(shí),每臺(tái)服務(wù)器主機(jī)從數(shù)據(jù)表中取對(duì)應(yīng)的 ID 區(qū)間緩存在本地,同時(shí)更新 sequence 表中的 value 最大值記錄。

現(xiàn)在我們新建一條記錄,比如設(shè)置一條 order 更新的規(guī)則,插入一行記錄如下:

INSERT INTO sequence (name,value) values('order_sequence',1000);i

當(dāng)服務(wù)器在獲取主鍵增長區(qū)段時(shí),首先訪問對(duì)應(yīng)數(shù)據(jù)庫的 sequence 表,更新對(duì)應(yīng)的記錄,占用一個(gè)對(duì)應(yīng)的區(qū)間。比如我們這里設(shè)置步長為 200,原先的 value 值為 1000,更新后的 value 就變?yōu)榱?1200。

  • 取到對(duì)應(yīng)的 ID 區(qū)間后,在服務(wù)器內(nèi)部進(jìn)行分配,涉及的并發(fā)問題可以依賴樂觀鎖等機(jī)制解決。

有了對(duì)應(yīng)的 ID 增長區(qū)間,在本地就可以使用 AtomicInteger 等方式進(jìn)行 ID 分配。

不同的機(jī)器在相同時(shí)間內(nèi)分配出去的 ID 可能不同,這種方式生成的唯一 ID,不保證嚴(yán)格的時(shí)間序遞增,但是可以保證整體的趨勢(shì)遞增,在實(shí)際生產(chǎn)中有比較多的應(yīng)用。

為了防止單點(diǎn)故障,sequence 表所在的數(shù)據(jù)庫,通常會(huì)配置多個(gè)從庫,實(shí)現(xiàn)高可用。

除了上面的幾種方案,實(shí)際開發(fā)中還可以應(yīng)用 Redis 作為解決方案,即通過 Redis Incr 命令來實(shí)現(xiàn)。

分庫分表以后擴(kuò)容

業(yè)務(wù)場(chǎng)景

設(shè)計(jì)電商網(wǎng)站的訂單數(shù)據(jù)庫模塊,經(jīng)過對(duì)業(yè)務(wù)增長的估算,預(yù)估三年后,數(shù)據(jù)規(guī)模可能達(dá)到 6000 萬,每日訂單數(shù)會(huì)超過 10 萬。

  • 存儲(chǔ)實(shí)現(xiàn),訂單作為電商業(yè)務(wù)的核心數(shù)據(jù),應(yīng)該盡量避免數(shù)據(jù)丟失,并且對(duì)數(shù)據(jù)一致性有強(qiáng)要求,肯定是選擇支持事務(wù)的關(guān)系型數(shù)據(jù)庫,比如使用 MySQL 及 InnoDB 存儲(chǔ)引擎。
  • 數(shù)據(jù)庫的高可用,訂單數(shù)據(jù)是典型讀多寫少的數(shù)據(jù),不僅要面向消費(fèi)者端的讀請(qǐng)求,內(nèi)部也有很多上下游關(guān)聯(lián)的業(yè)務(wù)模塊在調(diào)用,針對(duì)訂單進(jìn)行數(shù)據(jù)查詢的調(diào)用量會(huì)非常大。基于這一點(diǎn),我們?cè)跇I(yè)務(wù)中配置基于主從復(fù)制的讀寫分離,并且設(shè)置多個(gè)從庫,提高數(shù)據(jù)安全。
  • 數(shù)據(jù)規(guī)模,6000 萬的數(shù)據(jù)量,顯然超出了單表的承受范圍,參考《阿里巴巴 Java 開發(fā)手冊(cè)》中「單表行數(shù)超過 500 萬行」進(jìn)行分表的建議,此時(shí)需要考慮進(jìn)行分庫分表,那么如何設(shè)計(jì)路由規(guī)則和拆分方案呢?接下來會(huì)對(duì)此展開討論。

路由規(guī)則與擴(kuò)容方案

3 種路由規(guī)則:對(duì)主鍵進(jìn)行哈希取模、基于數(shù)據(jù)范圍進(jìn)行路由、結(jié)合哈希和數(shù)據(jù)范圍的分庫分表規(guī)則。

1. 哈希取模的方式

在這里插入圖片描述
根據(jù)不同的業(yè)務(wù)主鍵輸入,對(duì)數(shù)據(jù)庫進(jìn)行取模,得到插入數(shù)據(jù)的位置。

6000 萬的數(shù)據(jù)規(guī)模,按照單表承載百萬數(shù)量級(jí)來拆分,拆分成 64 張表,進(jìn)一步可以把 64 張表拆分到兩個(gè)數(shù)據(jù)庫中,每個(gè)庫中配置 32 張表。
當(dāng)新訂單創(chuàng)建時(shí),首先生成訂單 ID,對(duì)數(shù)據(jù)庫個(gè)數(shù)取模,計(jì)算對(duì)應(yīng)訪問的數(shù)據(jù)庫;接下來對(duì)數(shù)據(jù)表取模,計(jì)算路由到的數(shù)據(jù)表,當(dāng)處理查詢操作時(shí),也通過同樣的規(guī)則處理,這樣就實(shí)現(xiàn)了通過訂單 ID 定位到具體數(shù)據(jù)表。

優(yōu)點(diǎn)是數(shù)據(jù)拆分比較均勻。
缺點(diǎn)是不利于后面的擴(kuò)容。

假設(shè)訂單增長速度超出預(yù)估,數(shù)據(jù)規(guī)模很快達(dá)到了幾億的數(shù)量級(jí),原先的數(shù)據(jù)表已經(jīng)不滿足性能要求,數(shù)據(jù)庫需要繼續(xù)進(jìn)行拆分。

數(shù)據(jù)庫拆分以后,訂單庫和表的數(shù)量都需要調(diào)整,路由規(guī)則也需要調(diào)整,為了適配新的分庫分表規(guī)則,保證數(shù)據(jù)的讀寫正常,要進(jìn)行數(shù)據(jù)遷移,具體的操作,可以分為停機(jī)遷移不停機(jī)遷移兩種方式。

  • 停機(jī)遷移

停機(jī)遷移的方式比較簡(jiǎn)單,比如我們?cè)谑褂靡恍┚W(wǎng)站或者應(yīng)用時(shí),經(jīng)常會(huì)收到某段時(shí)間內(nèi)暫停服務(wù)的通知,一般是在這段時(shí)間內(nèi),完成數(shù)據(jù)遷移,將歷史數(shù)據(jù)按照新的規(guī)則重新分配到新的存儲(chǔ)中,然后切換服務(wù)。

  • 不停機(jī)遷移

動(dòng)態(tài)擴(kuò)容,依賴業(yè)務(wù)上的雙寫操作實(shí)現(xiàn),需要同時(shí)處理存量和增量數(shù)據(jù),并且做好各種數(shù)據(jù)校驗(yàn)。

數(shù)據(jù)庫擴(kuò)容方式有基于原有存儲(chǔ)增加節(jié)點(diǎn)和重新部署一套新的數(shù)據(jù)庫兩種策略。

重新部署新的數(shù)據(jù)庫存儲(chǔ)的步驟:

  • 創(chuàng)建一套新的訂單數(shù)據(jù)庫;
  • 在某個(gè)時(shí)間點(diǎn)上,將歷史數(shù)據(jù)按照新的路由規(guī)則分配到新的數(shù)據(jù)庫中;
  • 在舊數(shù)據(jù)庫的操作中開啟雙寫,同時(shí)寫入到兩個(gè)數(shù)據(jù)庫;
  • 用新的讀寫服務(wù)逐步替代舊服務(wù),同步進(jìn)行數(shù)據(jù)不一致校驗(yàn),最后完成全面切流。

2. 基于數(shù)據(jù)范圍進(jìn)行拆分

根據(jù)特定的字段進(jìn)行劃分不同區(qū)間,對(duì)訂單表進(jìn)行拆分中,如果基于數(shù)據(jù)范圍路由,可以按照訂單 ID 進(jìn)行范圍的劃分。
在這里插入圖片描述
同樣是拆分成 64 張數(shù)據(jù)表,可以把訂單 ID 在 3000萬 以下的數(shù)據(jù)劃分到第一個(gè)訂單庫,3000 萬以上的數(shù)據(jù)劃分到第二個(gè)訂單庫,在每個(gè)數(shù)據(jù)庫中,繼續(xù)按照每張表 100萬 的范圍進(jìn)行劃分。

基于數(shù)據(jù)范圍進(jìn)行路由的規(guī)則,當(dāng)進(jìn)行擴(kuò)容時(shí),可以直接增加新的存儲(chǔ),將新生成的數(shù)據(jù)區(qū)間映射到新添加的存儲(chǔ)節(jié)點(diǎn)中,不需要進(jìn)行節(jié)點(diǎn)之間的調(diào)整,也不需要遷移歷史數(shù)據(jù)。

缺點(diǎn)是數(shù)據(jù)訪問不均勻。按照這種規(guī)則,另外一個(gè)數(shù)據(jù)庫在很長一段時(shí)間內(nèi)都得不到應(yīng)用,導(dǎo)致數(shù)據(jù)節(jié)點(diǎn)負(fù)荷不均,在極端情況下,當(dāng)前熱點(diǎn)庫可能出現(xiàn)性能瓶頸,無法發(fā)揮分庫分表帶來的性能優(yōu)勢(shì)。

3. 結(jié)合數(shù)據(jù)范圍和哈希取模

設(shè)計(jì)這樣的一個(gè)路由規(guī)則,首先對(duì)訂單 ID 進(jìn)行哈希取模,然后對(duì)取模后的數(shù)據(jù)再次進(jìn)行范圍分區(qū)。
在這里插入圖片描述
通過哈希取模結(jié)合數(shù)據(jù)區(qū)間的方式,可以比較好地平衡兩種路由方案的優(yōu)缺點(diǎn)。當(dāng)數(shù)據(jù)寫入時(shí),首先通過一次取模,計(jì)算出一個(gè)數(shù)據(jù)庫,然后使用訂單 ID 的范圍,進(jìn)行二次計(jì)算,將數(shù)據(jù)分散到不同的數(shù)據(jù)表中。

避免了單純基于數(shù)據(jù)范圍可能出現(xiàn)的熱點(diǎn)存儲(chǔ),并且在后期擴(kuò)展時(shí),可以直接增加對(duì)應(yīng)的擴(kuò)展表,避免了復(fù)雜的數(shù)據(jù)遷移工作。

NoSQL 數(shù)據(jù)庫

對(duì)比關(guān)系型數(shù)據(jù)庫

關(guān)系型數(shù)據(jù)庫通過關(guān)系模型來組織數(shù)據(jù),在關(guān)系型數(shù)據(jù)庫當(dāng)中一個(gè)表就是一個(gè)模型,一個(gè)關(guān)系數(shù)據(jù)庫可以包含多個(gè)表,不同數(shù)據(jù)表之間的聯(lián)系反映了關(guān)系約束。

關(guān)系型數(shù)據(jù)庫對(duì)事務(wù)支持較好,支持 SQL 規(guī)范中的各種復(fù)雜查詢,比如 join、union 等操作。正是由于對(duì) SQL 規(guī)范的支持,也使得關(guān)系型數(shù)據(jù)庫對(duì)擴(kuò)展不友好,比較難進(jìn)行分布式下的集群部署。

NoSQL 數(shù)據(jù)庫特性

  • 良好的擴(kuò)展性,容易通過集群部署

關(guān)系型數(shù)據(jù)庫在進(jìn)行擴(kuò)展時(shí),要考慮到如何分庫分表、擴(kuò)容等,各種實(shí)現(xiàn)方案都比較重,對(duì)業(yè)務(wù)侵入較大。NoSQL 數(shù)據(jù)庫去掉了關(guān)系型數(shù)據(jù)庫的關(guān)系特性,對(duì)集群友好,這樣就非常容易擴(kuò)展。

  • 讀寫性能高,支持大數(shù)據(jù)量

關(guān)系型數(shù)據(jù)庫對(duì)一致性的要求較高,數(shù)據(jù)表的結(jié)構(gòu)復(fù)雜,讀寫的性能要低于非關(guān)系型數(shù)據(jù)庫。另外一方面,部分 NoSQL 數(shù)據(jù)庫采用全內(nèi)存實(shí)現(xiàn),更適合一些高并發(fā)的訪問場(chǎng)景。

  • 不限制表結(jié)構(gòu),靈活的數(shù)據(jù)模型

應(yīng)用關(guān)系型數(shù)據(jù)庫,需要通過 DML 語句創(chuàng)建表結(jié)構(gòu),數(shù)據(jù)表創(chuàng)建以后,增刪字段需要重新修改表結(jié)構(gòu)。如果使用 NoSQL,一般不需要事先為數(shù)據(jù)建立存儲(chǔ)結(jié)構(gòu)和字段,可以存儲(chǔ)各種自定義的數(shù)據(jù)。

關(guān)系型數(shù)據(jù)庫和非關(guān)系型數(shù)據(jù)庫是相輔相成的。從性能的角度來講,NoSQL 數(shù)據(jù)庫的性能優(yōu)于關(guān)系型數(shù)據(jù)庫,從持久化角度,關(guān)系型數(shù)據(jù)庫優(yōu)于 NoSQL 數(shù)據(jù)庫。
NoSQL 數(shù)據(jù)庫一般提供弱一致性的保證,實(shí)現(xiàn)最終一致性,CP 模型, NoSQL 關(guān)注的是 AP 模型,同時(shí)應(yīng)用 NoSQL 和關(guān)系型數(shù)據(jù)庫,可以滿足高性能的基礎(chǔ)上,同時(shí)保證數(shù)據(jù)可靠性。

NoSQL 數(shù)據(jù)庫應(yīng)用

Key-Value 數(shù)據(jù)庫

Key-Value 存儲(chǔ)就是 Map 結(jié)構(gòu),支持高性能的通過 Key 定位和存儲(chǔ)。通常用來實(shí)現(xiàn)緩存等應(yīng)用,典型的有 Redis 和 Memcached。

從性能的角度,為了提高讀寫效率,Redis 在最開始的版本中一直使用單線程模型,避免上下文切換和線程競(jìng)爭(zhēng)資源,并且采用了 IO 多路復(fù)用的技術(shù),提升了性能,另外在最近的版本更新中,Redis也開始支持多線程處理。

從存儲(chǔ)結(jié)構(gòu)的角度,Redis 支持多種數(shù)據(jù)結(jié)構(gòu),有豐富的應(yīng)用場(chǎng)景,并且針對(duì)不同的數(shù)據(jù)規(guī)模等,Redis 采取多種內(nèi)存優(yōu)化方式,盡量減少內(nèi)存占用。比如,List 結(jié)構(gòu)內(nèi)部有壓縮列表和雙向鏈表兩種實(shí)現(xiàn),在數(shù)據(jù)規(guī)模較小時(shí)采用 ZipList 實(shí)現(xiàn),特別是在新的版本更新中,又添加了 QuickList 的實(shí)現(xiàn),減少內(nèi)存的消耗。

從高可用的角度,作為一個(gè)內(nèi)存數(shù)據(jù)庫,Redis實(shí)現(xiàn)了AOF和RDB的數(shù)據(jù)持久化機(jī)制,另外,Redis支持了多種集群方式,包括主從同步,Sentinel和Redis Cluster等機(jī)制,提高了整體的數(shù)據(jù)安全和高可用保障。

文檔型數(shù)據(jù)庫

文檔型數(shù)據(jù)庫可以存儲(chǔ)結(jié)構(gòu)化的文檔,比如 JSON 或者 XML,從這個(gè)角度上看,文檔型數(shù)據(jù)庫比較接近關(guān)系型數(shù)據(jù)庫。但是對(duì)比關(guān)系型數(shù)據(jù)庫,文檔性數(shù)據(jù)庫中不需要預(yù)先定義表結(jié)構(gòu),并且可以支持文檔之間的嵌套,典型的比如 MongoDB,這一點(diǎn)和關(guān)系型數(shù)據(jù)庫有很大的不同。

以 MongoDB 為例,采用了基于 JSON 擴(kuò)展的 BSON 存儲(chǔ)結(jié)構(gòu),可以進(jìn)行自我描述,這種靈活的文檔類型,特別適合應(yīng)用在內(nèi)容管理系統(tǒng)等業(yè)務(wù)中。MongoDB 還具備非常優(yōu)秀的擴(kuò)展能力,對(duì)分片等集群部署的支持非常全面,可以快速擴(kuò)展集群規(guī)模。

列存儲(chǔ)數(shù)據(jù)庫

列式數(shù)據(jù)庫被用來存儲(chǔ)海量數(shù)據(jù),比如 Cassandra、HBase 等,特點(diǎn)是大數(shù)據(jù)量下讀寫速度較快、可擴(kuò)展性強(qiáng),更容易進(jìn)行分布式部署。

以 HBase 為例,HBase 支持海量數(shù)據(jù)的讀寫,特別是寫入操作,可以支持 TB 級(jí)的數(shù)據(jù)量。列式數(shù)據(jù)庫通常不支持事務(wù)和各種索引優(yōu)化,比如 HBase 使用 LSM 樹組織數(shù)據(jù),對(duì)比 MySQL 的 B+ 樹,在高并發(fā)寫入時(shí)有更好的性能。

圖形數(shù)據(jù)庫

在一些特定的應(yīng)用場(chǎng)景可以應(yīng)用特殊的數(shù)據(jù)庫,比如圖形數(shù)據(jù)庫。社交網(wǎng)絡(luò)中的用戶關(guān)系可以使用圖來存儲(chǔ),于是誕生了一些圖形數(shù)據(jù)庫,可以方便地操作圖結(jié)構(gòu)的相關(guān)算法,比如最短路徑、關(guān)系查找等。

ElasticSearch 索引

ElasticSearch 簡(jiǎn)介

Lucene 是一個(gè)開源的全文檢索引擎類庫,支持各種分詞以及搜索相關(guān)的實(shí)現(xiàn),可以極大地簡(jiǎn)化搜索開發(fā)的成本,但 Lucene 只是一個(gè)工具包,在實(shí)際項(xiàng)目中進(jìn)行二次開發(fā)。

ElasticSearch 是一個(gè)基于 Lucene 的分布式全文檢索框架,在 Lucene 類庫的基礎(chǔ)上實(shí)現(xiàn),可以避免直接基于 Lucene 開發(fā),這一點(diǎn)和 Java 中 Netty 對(duì) IO/NIO 的封裝有些類似。

ElasticSearch 開放了一系列的 RESTful API,基于這些 API,可以快捷地實(shí)現(xiàn)各種搜索功能。除了搜索相關(guān)的功能,ElasticSearch 還對(duì)分布式場(chǎng)景下的應(yīng)用有特別好的支持,包括良好的擴(kuò)展性,可以擴(kuò)展到上百臺(tái)服務(wù)器的集群規(guī)模,以及近似實(shí)時(shí)分析的索引實(shí)現(xiàn)。這些特點(diǎn),使得 ElasticSearch 在各類搜索場(chǎng)景、大數(shù)據(jù)分析等業(yè)務(wù)中廣泛應(yīng)用。

ElasticSearch 應(yīng)用

ElasticSearch 對(duì)搜索的支持非常好,但是和 NoSQL 數(shù)據(jù)庫一樣,對(duì)事務(wù)、一致性等的支持較低。

常見的數(shù)據(jù)庫-索引-緩存系統(tǒng)架構(gòu)圖:
在這里插入圖片描述
ElasticSearch 一般是作為持久性數(shù)據(jù)庫的輔助存儲(chǔ),是和 SQL & NoSQL 數(shù)據(jù)庫一起使用,對(duì)外提供索引查詢功能。關(guān)系型數(shù)據(jù)庫保證數(shù)據(jù)更新的準(zhǔn)確性,在關(guān)系型數(shù)據(jù)庫更新以后,通過 binlog 同步結(jié)合消息隊(duì)列分發(fā)的方式,來更新文件索引,提供一致性保證。

ELK stack

ElasticSearch 是由 Elastic 公司創(chuàng)建的,除了 ElasticSearch,Elastic 公司還有另外兩款產(chǎn)品,分別是 Logstash 及 Kibana 開源項(xiàng)目,這三個(gè)開源項(xiàng)目組合在一起稱為 ELK stack。

在 ELK 技術(shù)棧中,ElasticSearch 用于數(shù)據(jù)分析和檢索,Logstash 用于日志收集,Kibana 用于界面的展示,ELK 可以用于快速查詢數(shù)據(jù)并可視化分析,在日志處理、大數(shù)據(jù)等領(lǐng)域有非常廣泛的應(yīng)用。

索引是如何建立的

ElasticSearch 存儲(chǔ)的單元是索引,關(guān)系型數(shù)據(jù)庫是按照關(guān)系表的形式組織數(shù)據(jù),大部分 NoSQL 數(shù)據(jù)庫是 K-Value 的鍵值對(duì)方式。

ElasticSearch 索引的實(shí)現(xiàn)基于 Lucene,使用倒排索引的結(jié)構(gòu),倒排索引的引入,使得 ElasticSearch 可以非常高效地實(shí)現(xiàn)各種文件索引。倒排索引不光是在 ElasticSearch 等組件中應(yīng)用,它還是百度等搜索引擎實(shí)現(xiàn)的底層技術(shù)之一。在搜索引擎中,索引的建立需要經(jīng)過網(wǎng)頁爬取、信息采集、分詞、索引創(chuàng)建的過程,不過在 ElasticSearch 內(nèi)部存儲(chǔ)的實(shí)現(xiàn)中,數(shù)據(jù)的寫入可以對(duì)比搜索引擎對(duì)網(wǎng)頁的抓取和信息采集的過程,只需要關(guān)注分詞和索引的創(chuàng)建。

分詞和索引

分詞是在索引建立中特別重要的一個(gè)環(huán)節(jié),分詞的策略會(huì)直接影響索引結(jié)果。Lucene 提供了多種分詞器,分詞器是一個(gè)可插拔的組件,包括內(nèi)置的標(biāo)準(zhǔn)分詞器, 也可以引入對(duì)中文支持較好的 IKAnalyze 中文分詞器等。

假設(shè)我們?cè)?ElasticSearch 中新增了兩個(gè)文檔,每個(gè)文檔包含如下內(nèi)容:

  • 文檔1,Jerry and Tom are good friends.
  • 文檔2,Good friends should help each other.

英文是有單詞的,單詞之間通過空格進(jìn)行拆分,所以對(duì)英文的分詞相對(duì)容易,比如上面的內(nèi)容,可以直接對(duì)字符串按照空格拆分,得到分詞后的數(shù)組。

Jerry / / and / / Tom / / are / / good / / friends / . Good / / friends / / should / / help / / each / / other / .

一般來說,中文分詞用得比較多的策略是基于字典的最長字符串匹配方式,這種策略可以覆蓋大多數(shù)場(chǎng)景,不過還是有一小部分天然存在歧義的文檔是無法處理的。比如「學(xué)生會(huì)組織各種活動(dòng)」,按照最長串匹配的方式,可以切分成“學(xué)生會(huì)/組織各種活動(dòng)”,但實(shí)際要表達(dá)的可能是“學(xué)生/會(huì)/組織各種活動(dòng)”。

建立索引

索引存儲(chǔ)的結(jié)構(gòu)是倒排索引,倒排索引是相對(duì)于正排索引來說的,倒排索引描述了一個(gè)映射關(guān)系,包括文檔中分詞后的結(jié)果,以及分別包含這些單詞的文檔列表。

索引描述的其實(shí)就是關(guān)鍵詞和文檔的關(guān)系,正排索引就是“文檔—關(guān)鍵詞”的格式,倒排索引則相反,是“關(guān)鍵詞—文檔”的格式。可以看到,當(dāng)需要使用關(guān)鍵詞進(jìn)行檢索時(shí),使用倒排索引才能實(shí)現(xiàn)快速檢索的目的。

針對(duì)上面的分詞示例,我們簡(jiǎn)單起見,統(tǒng)一為小寫,把分詞之后的單詞組成一個(gè)不重復(fù)的分詞列表,為了更好地進(jìn)行查找,可以按照字典序排序。

and,are,each,friends,good,help,jerry,other,should,tom

比如,其中“friends”在文檔 1 和文檔 2 中都出現(xiàn)了,“Tom”和“Jerry”只在文檔 1 中出現(xiàn)了 1 次,其他的單詞也進(jìn)行同樣地處理,于是我們可以構(gòu)建下面的倒排索引:

分詞文檔列表
friends文檔 1,文檔 2
good文檔 1,文檔 2
jerry文檔 1,
tom文檔 1
以下省略

具體到數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn),可以通過實(shí)現(xiàn)一個(gè)字典樹,也就是 Trie 樹,對(duì)字典樹進(jìn)行擴(kuò)展,額外存儲(chǔ)對(duì)應(yīng)的數(shù)據(jù)塊地址,定位到具體的數(shù)據(jù)位置。

對(duì)比 B+ 樹

嚴(yán)格地說,這兩類索引是不能在一起比較的,B+ 樹描述的是索引的數(shù)據(jù)結(jié)構(gòu),而倒排索引是通過索引的組織形式來命名的。比如我們上面的例子中,倒排指的是關(guān)鍵詞和文檔列表的結(jié)構(gòu)關(guān)系。

對(duì)于數(shù)據(jù)庫來說,索引的作用是提高數(shù)據(jù)查詢的性能,考慮到磁盤尋址的特性,選擇了 B+ 樹作為索引的實(shí)現(xiàn)結(jié)構(gòu),可以更好地實(shí)現(xiàn)通過主鍵以及通過區(qū)間范圍查找的要求。

對(duì)于倒排索引,則是對(duì)應(yīng)具體的應(yīng)用場(chǎng)景,在搜索中是通過一些關(guān)鍵詞,定位到具體的文檔。所以倒排索引實(shí)現(xiàn)的是根據(jù)關(guān)鍵詞,也就是分詞的結(jié)果,去查找文檔,或者不同的網(wǎng)頁。

http://m.risenshineclean.com/news/60635.html

相關(guān)文章:

  • 河南疫情防控最新政策今日頭條新聞搜狗關(guān)鍵詞優(yōu)化軟件
  • 網(wǎng)站的困難app拉新推廣代理平臺(tái)
  • 凱天建設(shè)發(fā)展集團(tuán)有限公司網(wǎng)站盤多多網(wǎng)盤資源庫
  • 品牌網(wǎng)站開發(fā)動(dòng)態(tài)模塊廣州專業(yè)seo公司
  • 工程公司是做什么的谷歌seo排名技巧
  • 推廣網(wǎng)站掙錢windows優(yōu)化大師手機(jī)版
  • 臺(tái)州響應(yīng)式建站seo外鏈建設(shè)方法
  • 網(wǎng)站列表頁怎么做內(nèi)鏈搜索引擎排行榜
  • 網(wǎng)站之間的差異seo技術(shù)是干什么的
  • 設(shè)計(jì)logo怎么收費(fèi)泰安seo培訓(xùn)
  • 公司網(wǎng)站設(shè)計(jì)案例發(fā)外鏈軟件
  • 有什么做門窗展廳的設(shè)計(jì)網(wǎng)站百度收錄權(quán)重
  • 領(lǐng)手工在家做的網(wǎng)站2019廣告推廣的軟件
  • 購卡網(wǎng)頁怎么制作關(guān)鍵詞優(yōu)化軟件
  • 靜態(tài)做網(wǎng)站百度推廣官方網(wǎng)站登錄入口
  • 社交網(wǎng)站百度搜索推廣費(fèi)用
  • 網(wǎng)站綜合建設(shè)筆記可以免費(fèi)發(fā)布廣告的平臺(tái)有哪些
  • 哈爾濱整站優(yōu)化百度提交入口
  • 汽車網(wǎng)站開發(fā)流程品牌整合營銷傳播
  • 中國網(wǎng)站有哪些如何自己搭建網(wǎng)站
  • wordpress標(biāo)簽后綴名html培訓(xùn)行業(yè)seo整站優(yōu)化
  • 如何做有后臺(tái)的網(wǎng)站正規(guī)網(wǎng)絡(luò)推廣服務(wù)
  • 做柜子網(wǎng)站在線培訓(xùn)課程
  • 秦皇島做網(wǎng)站seo的快排seo軟件
  • 網(wǎng)站開發(fā)應(yīng)用到的技術(shù)名詞百度seoo優(yōu)化軟件
  • 企業(yè)微信有哪些功能寧波seo軟件
  • 農(nóng)產(chǎn)品網(wǎng)站建設(shè)投標(biāo)書百度開戶是什么意思
  • wordpress調(diào)用第一張圖片合肥網(wǎng)絡(luò)優(yōu)化公司有幾家
  • 襄陽建設(shè)21網(wǎng)站搜索引擎營銷有哪些方式
  • 深圳網(wǎng)站建設(shè)快速排名自動(dòng)seo網(wǎng)站源碼