search
尋找貓咪~QQ 地點 桃園市桃園區 Taoyuan , Taoyuan

如何讓你的分庫分表中間件支持emoji表情

隨著微信等社交軟體的興起,支持emoji表情幾乎成為越來越多的互聯網產品的標配。讓一個互聯網項目支持emoji表情,至少要從三個層面支持:展現層、應用層、數據存儲層。

  • 展現層要能將emoji表情的編碼按照正確的色彩和圖片展示出來,這就需要展現層本身維護一個圖片和編碼的映射庫,就是常說的表情庫,比如你現在用來看本文的瀏覽器就能正確顯示這個笑臉,如果把這篇文章在Linux終端下打開,肯定會顯示亂碼。

  • 應用層支持emoji表情,是指在像Java這種應用層代碼可以支持utf8mb4編碼的傳輸,主要是能在內存中表示這種編碼,並能正確地從存儲層傳輸到展現層。

  • 數據存儲層,以MySQL為例,比如這篇文章下面的評論欄位,在簡書的資料庫中存儲的時候要設置為utf8mb4編碼格式,否則會報一些非法字元的錯誤。

通常情況下支持emoji的注意事項

這裡要重點強調兩點在支持emoji表情的設置中要注意的事項:

1、把資料庫欄位設置為utf8mb4編碼,而不是server配置,也不是schema的設置,因為真正存儲的是欄位,直接在線上執行alter語句修改欄位的編碼格式才能真正起到效果,而修改mysql_server的配置文件然後重啟mysql不僅沒有卵用,而且線上重啟資料庫也是不能被接受的。

2、SET NAMES UTF8MB4語句在每個資料庫連接建立后執行,幾乎是必須的,這個和JDBC本身的限制有關,具體原因不再深究,很多網上同學的博文也顯示在Connection中顯式指明utf8mb4編碼是最佳實踐

中間件執行SET NAMES UTF8MB4報錯怎麼辦

然而,現實情況是很多大型的互聯網應用都會使用開源的或者自研的分庫分表中間件,這類分庫分表中間件多數都會有個限制:SQL語句都要帶上分庫或者分表欄位。因為這類中間件多數應用在OLTP的場景,沒有分庫分表欄位意味著跨庫跨表查詢,而跨庫跨表查詢往往開銷比較大,而且會引發分散式事務問題,所以很多中間件對不帶分庫分表欄位的查詢支持並不好,甚至極端的乾脆就不支持。

於是在分庫分表的場景中,SET NAMES UTF8MB4語句很難被正確地執行,甚至報錯,那麼就需要對中間件做一些hack,以支持這種剛性的emoji表情需求。

筆者在之前的一篇文章中介紹過分庫分表中間件的基本原理,即重寫JDBC API,應用上層獲取的資料庫連接Connection對象並不是真實的物理連接,而是一種自定義的抽象的Connection,所以解決問題的基本思路就是在中間件底層獲取物理連接的時候立即執行SET NAMES UTF8MB4語句,這樣底層的每個物理連接的字符集都會在執行業務SQL之前就被設置好utf8mb4字符集了。

下面以支付寶開源的分庫分表中間件zdal 為例,示範如何支持utf8mb4:

首先找到中間件創建物理連接的位置,在LocalManagedConnectionFactory.java中

這裡的con就是真實的物理連接,沒有分庫分表欄位的限制,於是執行代碼

即可把當前Connection設置為utf8mb4字符集。

但是有時候我們不想就這樣硬編碼,希望能夠把utf8mb4設置為可選的,這裡分析上面的代碼,發現有Properties選項,zdal傳遞Properties的配置文件可以參考 ,所以比較簡單優雅的解決方案是在配置文件里加個properties選項,然後根據這個選項來決定是否設置utf8mb4,比如這樣:

然後在LocalManagedConnectionFactory中判斷supportEmoji來決定是否支持utf8mb4:

總結

多數分庫分表中間件實現的細節大同小異,所以其他分庫分表中間件的修改方法也基本類似,關鍵在於找到中間件內部是如何獲取資料庫物理連接的,然後能在當前連接中正確設置utf8mb4字符集即可。



熱門推薦

本文由 yidianzixun 提供 原文連結

寵物協尋 相信 終究能找到回家的路
寫了7763篇文章,獲得2次喜歡
留言回覆
回覆
精彩推薦