微微科技技術團隊(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中。數據結構
具體系統架構設計以下圖所示。
商家商品搜索系統架構設計
這個步驟是利用canal從2個獨立的MySQL8數據庫中,抽取須要的表到搜索服務的MySQL數據庫。
進入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給的示例,咱們能夠參考其配置。
canaldeploy instance 源數據庫配置
canaldeploy instance kafka topic配置
至此canal deployer搭建完成。
咱們須要利用canal.adapter將kafka topic中的binlog json數據,通過清洗轉換等操做,存儲到MySQL8中。因爲canal原生是不支持MySQL8的,故咱們須要作一些調整。
解壓canal.adapter-1.1.4.tar.gz,進入canaladapter/lib目錄,移除mysql-connector-java-5.1.40.jar,導入mysql-connector-java-8.0.18.jar
進入canaladapter/conf目錄,編輯application.yml文件,主要配置消費kafka、源數據庫信息和搜索系統數據庫信息,以下所示:
ETL到MySQL8配置
接着,進入canaladapter/conf/rdb目錄,以官方提供的mytest_user.yml爲例,配置kafka topic名、源數據庫名、源數據表名,以及目標數據庫名和目標數據表名,建議一張表對應一個yml文件。
ETL表結構映射配置
進入canaladapter/bin目錄,執行./startup.sh,啓動canal adapter,觀察logs/adapter/adapter.log日誌文件,手動在搜索系統數據庫新增一條記錄,看是否會打印以下日誌,即有2條記錄,一條INFO,一條DEBUG,則表示配置成功。
canaladapter日誌
至此,數據ETL階段搭建完成,數據可從兩個不一樣的MySQL8數據庫,實時同步到搜索服務的MySQL數據庫。
進入canaladapter/conf目錄,編輯application.yml文件,主要配置消費kafka、搜索系統數據庫,和ES鏈接信息,以下所示:
canaladapter MQ及mysql配置
canaladapter ES配置
進入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映射.
以官方的biz_order.yml爲例,vim biz_order.yml,配置父子文檔映射:
配置父子文檔映射
進入kibana頁面,點擊Dev Tools,執行以下命令,便可創建索引及父子文檔映射:
創建index和父子文檔映射
其中,ES6和kibana的安裝,在此無特別配置,不作贅述。
進入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 核心技術資料,這是部分資料目錄:
公衆號後臺回覆arch028
獲取資料::