天天看點

Liferay研究之卅一:Database Sharding(資料庫分片)

Database Sharding是什麼?

其實就是一種分布式計算,通過業務邏輯将不同的分類的資料儲存到不同的資料庫(具有相同的表結構)中。簡單的說是一種負載均衡技術,因為每個表中的資料少了,查詢速度就快了,系統能承受的負載也就大了。很多大公司都在用這種技術,比如Google, Facebook, Wikipedia等等。

Liferay的實作政策是什麼?

Liferay實作的是根據Portal Instance來進行分布的,也就是說,不同的portal instance的資料,儲存在不同的資料庫中。同一個portal instance的資料,隻在一個資料庫中。當然,一些全局的資料,比如ClassName,Company, Counter等資料是儲存在一個節點(default)上的。

Liferay中的配置方式

1、首先你的系統上要有多個Portal Instances

比如babaodi.com, liushining.cn, smilingleo.cn等

2、安裝多個資料庫(也可以是一個伺服器上的多個執行個體),可以是異構的,通過create_minimal的sql腳本建立最小資料庫。

3、在portal.properties中将shard-data-source-spring.xml的注釋去掉。并添加對應的配置内容,比如:

jdbc.default.driverClassName=com.mysql.jdbc.Driver

jdbc.default.url=jdbc:mysql://localhost/lportal?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false

jdbc.default.username=

jdbc.default.password=

jdbc.one.driverClassName=com.mysql.jdbc.Driver

jdbc.one.url=jdbc:mysql://localhost/lportal1?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false

jdbc.one.username=

jdbc.one.password=

jdbc.two.driverClassName=com.mysql.jdbc.Driver

jdbc.two.url=jdbc:mysql://localhost/lportal2?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false

jdbc.two.username=

jdbc.two.password=

shard.available.names=default,one,two

這樣,你的系統就可以将不同的portal instance的資料儲存到不同的資料庫中了。

實作原理

具體的實作Liferay采用了AOP, 在shard-data-source-spring.xml中定義了一個ShardAdvice,

<aop:config>

<aop:aspect ref="com.liferay.portal.dao.shard.ShardAdvice">

<aop:around pointcut="bean(com.liferay.portal.service.AccountLocalService.impl)" method="invokeAccountService" />

<aop:around pointcut="bean(com.liferay.portal.service.CompanyLocalService.impl)" method="invokeCompanyService" />

<aop:around pointcut="bean(com.liferay.portal.service.UserLocalService.impl)" method="invokeUserService" />

<aop:around pointcut="bean(*Persistence.impl) or bean(*Finder.impl)" method="invokePersistence" />

<aop:around pointcut="execution(void com.liferay.portal.convert.messaging.ConvertProcessMessageListener.receive(..))" method="invokeGlobally" />

<aop:around pointcut="execution(void com.liferay.portal.events.StartupHelper.*(..))" method="invokeGlobally" />

</aop:aspect>

</aop:config>

可以看出,所有持久化方法都調用invokePersistence方法,而該方法中負責通過instances % shards的簡單hash算法擷取一個資料源(被保持在ThreadLocal中)。

替代技術

Database Sharding是與業務相關的分布式資料處理技術,不夠通用,而且多個資料源就存在多個單點問題。

一個比較好的通用解決方案是C-JDBC(Sequoia),把硬體RAID的概念演化為軟體的Raidb, 即解決了分布式運算的問題,又可以通過RAIDb1的方式解決單點問題。

當然,C-JDBC是一種沒錢買“磁盤陣列”的廉價替換方案,如果你已經有了陣列,那麼就不需要這個技術了。(選購伺服器等基礎設施時,就需要考慮好用什麼樣的軟體技術,否則會浪費錢,很多錢。)