Hibernate與數據庫分表

數據庫分片(shard)是一種在數據庫的某些表變得特別大的時候採用的一種技術。mysql

 

經過按照必定的維度將表切分,可使該表在經常使用的檢索中保持較高的效率,而那些不經常使用的記錄則保存在低訪問表中。好比:銷售記錄按照時間來切分。(橫向切分)git

也能夠根據地域進行拆分,使得每一個地區訪問本身的表從而進行負載均衡。(縱向切分)github

也能夠縱橫切分,使表拆的更細緻。sql

也能夠分庫,讓不一樣的數據存放在不一樣的服務器上,從而進一步均衡負載。數據庫

 

當遇到這樣的事情的時候,若是不是採用了MongoDB這種自動拆表的工具,通常來講,都要本身實現一下切表的策略。其實,Hibernate中已經提供了一個很好用的包:服務器

Hiberante Shard,該包是Google貢獻給Hibernate社區的。根據其資料顯示,如今這個包仍是有些限制的。session

好比:不可以進行跨表的order by,不能實現跨表的distinct,不能採用基礎數據類型(如int)做爲ID的類型。app

 

可是它能夠支持跨表的惟一ID,跨表的查詢,跨表的累計...負載均衡

並且它彷佛只要少許的代碼和簡單的配置就可使用,看來它真的是一個很好的工具。值得一試。ide

很不幸,網上的例子太少了,只找到了一段例子代碼:

Hibernate Shards 數據的水平、垂直切割系列

 

這段代碼下載以後運行了,因爲數據量太少,而且生成在同一個表中,沒法證實Hibernate Shards的做用。

官方網站的資料彷佛也是惜墨如金,沒有解釋的很是詳細。

 

    Shards如何配置,如何使用呢?

    一個工程裏,有的表要切分,有的沒必要,如何作?

    Shard和ebean如何結合使用呢?

 

帶着這些課題,我開始了對Hibernate Shard的調查和研究。

 

Hibernate是一種ORM的包,它要有來自mapping.xml的「原型」,來自Java的Entity纔可以造成ORMapping,還有一個數據庫的表,它們的關係是一對一。

而若是採用分片技術,那麼應該是一個原型,一個Entity,對應數據庫的若干個結構相同的表。

 

在Hibernate Shard中,經過一個叫作「策略」的東西來完成這樣的過程。

它容許經過定義不一樣的策略,來將不一樣分類的數據存放在不一樣的表(乃至庫)中,而這個要經過一組和hibernate.cfg.xml結構同樣的配置文件來定義。就像下面這樣:

複製代碼

1 <?xml version='1.0' encoding='utf-8'?>
 2 <!DOCTYPE hibernate-configuration PUBLIC 
 3     "-//Hibernate/Hibernate Configuration DTD//EN" 
 4     "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
 5 <hibernate-configuration>
 6 <session-factory>
 7       <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
 8       <property name="connection.url">jdbc:mysql://localhost/test</property>
 9       <property name="connection.username">root</property>
10       <property name="connection.password">root</property>
11       <property name="connection.pool_size">10</property>
12       <property name="show_sql">true</property>
13       <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
14       <property name="hbm2ddl.auto">validate</property>
15       <property name="hibernate.connection.shard_id">0</property>
16       <property name="hibernate.shard.enable_cross_shard_relationship_checks">false</property>
17 
18 
19       <mapping resource="ContactEntity.hbm.xml" />
20 </session-factory>
21 
22 </hibernate-configuration>

複製代碼

 

而後在生成SessionFactory的時候採用這樣的代碼:

複製代碼

1 private static SessionFactory createSessionFactory() {
 2         Configuration prototypeCfg = new Configuration()
 3             .configure("shard0.hibernate.cfg.xml");
 4         List<ShardConfiguration> shardCfgs = new ArrayList<ShardConfiguration>();
 5         shardCfgs.add(buildShardConfig("shard0.hibernate.cfg.xml"));
 6         shardCfgs.add(buildShardConfig("shard1.hibernate.cfg.xml"));
 7         ShardStrategyFactory strategyFactory = buildShardStrategyFactory();
 8         ShardedConfiguration shardedConfig = new ShardedConfiguration(
 9             prototypeCfg, shardCfgs, strategyFactory);
10        return shardedConfig.buildShardedSessionFactory();
11    }

複製代碼

而策略則分爲三種:

   ShardAccessStrategy

   ShardSelectionStrategy

   ShardResolutionStrategy

咱們須要上述三種策略纔可以構建Hibernate的SessionFactory,就像下面這樣。

複製代碼

1 private static ShardStrategyFactory buildShardStrategyFactory() {
 2        return new ShardStrategyFactory() {
 3            public ShardStrategy newShardStrategy(List<ShardId> shardIds) {
 4                ShardSelectionStrategy ss = new MyShardSelectionStrategy(shardIds);
 5                ShardResolutionStrategy rs = new MyShardResolutionStrategy(shardIds);
 6                ShardAccessStrategy as = new SequentialShardAccessStrategy();
 7                return new ShardStrategyImpl(ss, rs, as);
 8            }
 9        };
10     }

複製代碼

那麼這三種策略都是什麼,應該怎麼配置呢?

這三種策略的文檔說明和代碼說明不怎麼一致。(說實在的,這段文檔真的沒怎麼看懂,幸運的是,它是OpenSource的)

  ShardAccessStrategy   文檔說,切片訪問策略,它定義了Hibernate如何和多個Shard之間進行訪問。

                幸運的是,Hibernate已經爲咱們建立了兩個定義好了的ShardAccessStrategy,它們是:

                 SequentialShardAccessStrategy  (順序切片訪問策略) 和  ParallelShardAccessStrategy(並行切片訪問策略)

                順序切片訪問策略 如其名稱所言,它按照順序切片,資料顯示,它有可能在訪問無序數據時性能偏低,如果這種狀況,官方建議使用LoadBalancedSequentialShardAccessStrategy。

                並行切片訪問策略 如其名稱所言,它提供了並行訪問的策略,因此它同時要求提供一個並行策略執行器。 —— 聽起來挺可貴,並且,介紹資料說——這超綱了。

                先無論這麼多吧,假設咱們訪問的數據是一種,按地區、按年份增加的數據,每一個城市個月增加量都在10萬~1百萬,那麼咱們要在這裏採用什麼策略呢?

  數據是按照時間排序的,因此,咱們能夠採用SequentialShardAccessStrategy,按月分片,而且按照地區分片。

 

        ShardSelectionStrategy  文檔說定義瞭如何建立一個新對象。

        代碼上的註釋說:Determine the specific shard on which this object should reside

         也就是說,這個是定義哪一個領域用來存放這條數據的。

       ShardResolutionStrategy 文檔說是表示如何將數據進行分流的。好比咱們提到的按地區、按月分片。那麼數據須要根據這些條件存放在不一樣的表中。而ShardResolutionStrategy就是幫助咱們來完成這個動做的。

        代碼註釋上說:Determine the shards on which an object might live

 

 

       在ShardStrategyFactory的newShardStrategy方法中傳入的參數List<ShardId> shardIds會幫助咱們進行選擇區域動做。ShardId會定位對應的Continent。

       我跟蹤了一下那段例子代碼,這裏的shardIds表示有多少個hibernate.cfg.xml文件中的不一樣的shard_id字段的值。而ShardSelectionStrategy在Insert的時候會執行,而ShardResolutionStrategy則會在Select的時候執行。(update/delete還沒有嘗試。)

       咱們能夠在ShardSelectionStrategy中創建本身的策略,好比,按照時間,按照地區來區分數據。從而把數據存放在不一樣的中。

       由於shardx.hibernate.cfg.xml指定了不一樣的數據庫,因此,到這裏能夠實現分庫了。

      而對於那些沒必要分表的直接return 0便可。

 

     初版的測試代碼在這裏下載

---------------

下一步我將研究一下,如何分表和如何結合Ebean。

相關文章
相關標籤/搜索