本文的多租戶是基于多數(shù)據(jù)庫進行實現(xiàn)的,數(shù)據(jù)是通過不同數(shù)據(jù)庫進行隔離。
首先針對多租戶配置了多個數(shù)據(jù)庫,在 MyCat 的 schema.xml 中配置了多個 schema。
在 server.xml 中配置了一個用戶:
后面會使用 MyCat 注解(就是注釋)方式根據(jù)不同的標識,將操作指向不同的數(shù)據(jù)庫。
標識有很多種方式可以加以區(qū)分,下面使用最簡單的一種,通過不同的二級域名進行識別。二級域名和數(shù)據(jù)庫對應的信息可以通過全局庫或者公共庫進行存儲,還可以是簡單的配置文件進行配置,不過下面代碼只是為了演示,因此配置信息都是寫死在代碼中的。
假設存在以下二級域名,分別對應不同的數(shù)據(jù)庫:
通過過濾器,在用戶請求時根據(jù)請求地址設置當前請求使用的數(shù)據(jù)庫:
這段代碼只是很簡單的判斷,根據(jù)不同的字符串設置不同的數(shù)據(jù)庫。使用了一個靜態(tài)的本地線程變量來存儲數(shù)據(jù)庫信息。
使用 MyBatis 和數(shù)據(jù)庫進行操作時,所有執(zhí)行的 sql 都是通過 MappedStatement 獲取的,雖然通過攔截器方式也能給 sql 添加注解,但是實現(xiàn)起來有點復雜。通過重寫 MappedStatement 會簡單很多,但是你也需要保證重寫的這個類能夠替代默認的類。
重寫很簡單,只需要修改原有的 getBoundSql
方法:
這段代碼就是在返回 BoundSql 前,修改 sql,添加 /*!mycat:schema=數(shù)據(jù)庫*/
,具體的數(shù)據(jù)庫從過濾器的靜態(tài)方法獲取,由于每一個請求都會經(jīng)過過濾器(特別注意,如果是任務一類的調(diào)用,不需要經(jīng)過過濾器,這種情況需要處理任務執(zhí)行時數(shù)據(jù)庫的綁定,這需要根據(jù)具體業(yè)務實現(xiàn)),因此這里的操作一定能獲取到具體的數(shù)據(jù)庫。增加這個注解后,MyCat 執(zhí)行時就會自動將數(shù)據(jù)庫的操作發(fā)送到指定的數(shù)據(jù)庫上執(zhí)行,通過這種方式就實現(xiàn)了一種簡單的多租戶方式。
如果大家愿意分享更好的設計方案,歡迎留言。