百萬級商品數據實時同步,查詢結果秒出

微微科技技術團隊(Kevin)
https://juejin.im/post/5e6989...

前陣子老闆安排了一個新任務,要建設一個商家商品搜索系統,可以爲用戶提供快速、準確的搜索能力,在用戶輸入搜索內容時,要能從商家名稱和商品名稱兩個維度去搜索,搜索出來的結果,按照準確率排序,並按商家所屬商品的關聯關係,來組合數據結構,同時提供API給業務系統調用。java

背景很簡單,現實蠻複雜!咱們面臨如下幾個難題:mysql

①商家數據庫和商品數據庫是多臺不一樣的服務器,而且數據量達百萬級,如何才能實現跨數據庫的數據同步呢?sql

②商家和商品的數據是有從屬關係的,否則就會把肯德基的香辣雞腿堡掛到麥當勞去,這就尷尬了!數據庫

③商家商品數據是常常更新的,好比修改價格、庫存、上下架等,那搜索服務可不能搜出一堆過期的數據,若是客戶明明搜出來的商品,點進去後卻已下架了,那麼客戶就要吐槽了!如何實現搜索數據與源數據庫增刪改均實時同步呢?編程

帶着以上3個問題,咱們開始了搜索服務的總體架構設計。json

系統架構設計思路

爲了設計出合適的系統架構,咱們分析了現狀。
首先,商家數據和商品數據分別存儲在2個獨立的MySQL8數據庫,爲知足商家數據和商品數據的關聯,咱們須要將兩個庫中所須要的表實時ETL到咱們的搜索系統數據庫。vim

其次,數據從商家、商品數據庫ETL到搜索系統數據庫後,須要實時的組合成爲商家關聯商品數據結構,並以父子文檔的格式,存儲到ES中。服務器

最後,商家、商品數據庫的增刪改操做,須要實時的同步到ES中,也就是ES中的數據,須要支持實時的增長、刪除和修改。微信

爲此,咱們設計了2個canal組件,第一個canal實現數據ETL,把商家、商品數據庫的某些表及字段,抽取到搜索服務數據庫;再利用第二個canal,讀取搜索服務MySQL數據庫的binlog,實時傳輸到kafka消息隊列,再由canal adapter對數據進行關聯、父子文檔映射等,將處理好的數據存儲到ElasticSearch中。數據結構

具體系統架構設計以下圖所示。

商家商品搜索系統架構設計

項目實戰

一、環境及軟件說明

  • 操做系統:CentOS 7
  • canal:canal.adapter-1.1.4
  • canal.deployer-1.1.4
  • kafka:kafka_2.12-2.3.0
  • ElasticSearch:elasticsearch-6.3.2
  • kibana:kibana-6.3.2

二、利用Canal實現數據ETL到MySQL8

這個步驟是利用canal從2個獨立的MySQL8數據庫中,抽取須要的表到搜索服務的MySQL數據庫。

2.1 安裝canaldeployer
  • (1)解壓canal.deployer-1.1.4.tar.gz
  • (2)配置canal deployer

進入canaldeployer/conf目錄,修改canal.properties文件,主要配置serverMode、MQ和destination三部分。

首先,咱們serverMode修改成kafka模式,增長系統緩衝能力以及提升系統穩定性:

serverMode

接着,配置kafka的MQ信息(kafka請自行安裝):

kafka MQ信息

最後,配置須要實例化的instance,這裏配置了3個,表示canal deploy會啓動這3個實例,同步MySQL的binlog到kafka的topic內。以下圖所示:

destinations實例配置

(3)配置canal deployer instance

進入canaldeployer/conf/example目錄,發現有一個instance.properties文件,這是canal給的示例,咱們能夠參考其配置。

  • ①咱們拷貝整個example目錄,並重命名爲上個步驟配置的destination之一,如xxxsearch;
  • ②進入xxxsearch目錄,編輯instance.properties文件,主要配置源數據庫信息、所需數據表及字段,以及指定kafka的topic名,這樣源數據庫的binlog就會轉換爲json數據,並實時的經過canal deployer傳輸到kafka該topic中。以下所示:
canaldeploy instance 源數據庫配置

canaldeploy instance kafka topic配置

  • ③進入canaldeployer/bin目錄,執行./startup.sh,啓動canal deployer及所屬實例。

至此canal deployer搭建完成。

2.2 安裝canal.adapter

咱們須要利用canal.adapter將kafka topic中的binlog json數據,通過清洗轉換等操做,存儲到MySQL8中。因爲canal原生是不支持MySQL8的,故咱們須要作一些調整。

  • (1)增長MySQL8鏈接驅動

解壓canal.adapter-1.1.4.tar.gz,進入canaladapter/lib目錄,移除mysql-connector-java-5.1.40.jar,導入mysql-connector-java-8.0.18.jar

  • (2)配置canal adapter,使數據輸出到MySQL8。

進入canaladapter/conf目錄,編輯application.yml文件,主要配置消費kafka、源數據庫信息和搜索系統數據庫信息,以下所示:

ETL到MySQL8配置

接着,進入canaladapter/conf/rdb目錄,以官方提供的mytest_user.yml爲例,配置kafka topic名、源數據庫名、源數據表名,以及目標數據庫名和目標數據表名,建議一張表對應一個yml文件。

ETL表結構映射配置

  • (3)啓動canaladapter

進入canaladapter/bin目錄,執行./startup.sh,啓動canal adapter,觀察logs/adapter/adapter.log日誌文件,手動在搜索系統數據庫新增一條記錄,看是否會打印以下日誌,即有2條記錄,一條INFO,一條DEBUG,則表示配置成功。

canaladapter日誌

至此,數據ETL階段搭建完成,數據可從兩個不一樣的MySQL8數據庫,實時同步到搜索服務的MySQL數據庫。

三、實現數據多表關聯、父子文檔映射
(1)配置第二個canal的canaladapter

進入canaladapter/conf目錄,編輯application.yml文件,主要配置消費kafka、搜索系統數據庫,和ES鏈接信息,以下所示:

canaladapter MQ及mysql配置

canaladapter ES配置

(2)配置多表關聯

進入canaladapter/conf/es目錄,vim mytest_user.yml,編輯多表關聯配置:

多表關聯配置

注意,sql支持多表關聯自由組合, 可是有必定的限制:

  • (a)主表不能爲子查詢語句
  • (b)只能使用left outer join即最左表必定要是主表
  • (c)關聯從表若是是子查詢不能有多張表
  • (d)主sql中不能有where查詢條件(從表子查詢中能夠有where條件可是不推薦, 可能會形成數據同步的不一致, 好比修改了where條件中的字段內容)
  • (e)關聯條件只容許主外鍵的'='操做不能出現其餘常量判斷好比: on a.role_id=b.id and b.statues=1
  • (f)關聯條件必需要有一個字段出如今主查詢語句中好比: on a.role_id=b.id 其中的 a.role_id 或者 b.id 必須出如今主select語句中
  • (g)Elastic Search的mapping 屬性與sql的查詢值將一一對應(不支持 select *), 好比: select a.id as _id, a.name, a.email as _email from user, 其中name將映射到es mapping的name field, _email將映射到mapping的_email field, 這裏以別名(若是有別名)做爲最終的映射字段. 這裏的_id能夠填寫到配置文件的 _id: _id映射.
(3)配置父子文檔

以官方的biz_order.yml爲例,vim biz_order.yml,配置父子文檔映射:

配置父子文檔映射

(4)在ElasticSearch6中,創建index和父子文檔映射關係

進入kibana頁面,點擊Dev Tools,執行以下命令,便可創建索引及父子文檔映射:

創建index和父子文檔映射

其中,ES6和kibana的安裝,在此無特別配置,不作贅述。

(5)啓動canal adapter

進入canaladapter/bin目錄,執行./startup.sh,啓動canal adapter,觀察logs/adapter/adapter.log日誌文件,手動在搜索系統數據庫新增一條記錄,看是否會打印以下日誌,如打印則表示配置成功。

正確配置adapter日誌示例

運行結果

如今,咱們能夠經過kibana來執行DSL語句來查詢看看。咱們事先已在商家系統中增長了一個「肯德基」商店,而後在商品系統中添加了「西紅柿」和」新鮮西紅柿「2個商品,並將商品關聯到「肯德基」上。接着咱們查詢」肯德基「或者「西紅柿」,獲得如下是查詢的結果(去除了ES默認字段):

經過DSL查詢的結果
由圖可見,咱們能夠經過商家名查詢商品,也可經過商品名查詢商店和商品,而且canal支持數據的實時增刪改,因此ES的數據也會與商家系統和商品系統保持一致,同時數據結構包含商家及對應的商品,知足業務需求。

五、總結

至此,基於Canal、kafka、MySQL八、ElasticSearch6技術的商家商品搜索系統基礎框架搭建完成。咱們採用canal deployer實時讀取商家、商品系統的MySQL數據庫binlog,併發送至kafka,接着由canal adapter消費kafka,並將binlog json數據進行多表關聯、父子文檔映射,最後存儲到ES6中,供上層搜索服務調用。

**搜索服務系統最終成功上線,爲公司百萬級商家商品提供實時數據同步,秒級搜索結果展現,達到業務要求,老闆說了,給研發團隊每人加個雞腿!想一想還有點小激動,嘿嘿~~
**

推薦閱讀

學習資料分享

收集準備了 12 套 微服務、Spring Boot、Spring Cloud 核心技術資料,這是部分資料目錄:

  • Spring Security 認證與受權
  • Spring Boot 項目實戰(中小型互聯網公司後臺服務架構與運維架構)
  • Spring Boot 項目實戰(企業權限管理項目))
  • Spring Cloud 微服務架構項目實戰(分佈式事務解決方案)
  • Spring Cloud + Spring Boot + Docker 全套視頻教程
  • Spring Cloud 網站項目實戰(房產銷售)
  • Spring Cloud 微服務項目實戰(大型電商架構系統)
  • 單點登錄基礎到實戰
  • Spring Boot 項目實戰(企業微信點餐系統)(初級實戰)
  • Spring Cloud 互聯網應用項目實戰(天氣預報系統)
  • Spring 源碼深度解析 + 註解開發全套視頻教程
  • Spring Boot 項目實戰(理財產品系統)

    公衆號後臺回覆arch028獲取資料::

相關文章
相關標籤/搜索