Hibernate Shards 概略

来自 hibernate_shards中文参考指南

分片策略

配置的入口是接口
org.hibernate.shards.strategy.ShardStrategy:


public interface ShardStrategy {
  ShardSelectionStrategy getShardSelectionStrategy();
  ShardResolutionStrategy getShardResolutionStrategy();
  ShardAccessStrategy getShardAccessStrategy();
}



ShardAccessStrategy
决定在多个片段(shards)上怎样执行数据库操作,无论什么时间你在分段上执行一次查
询都要询问 ShardAccessStrategy

接口的两个实现
SequentialShardAccessStrategy                   
查询在你的片段(shards)上是顺序地执行的。

ParallelShardAccessStrategy
查询在你的片段(shards)上是并发地执行的

ShardSelectionStrategy
决定在哪个片段(shard)上创建一个新对象
提供了一个轮询(round-robin)的实现(RoundRobinShardSelectionStrategy)
程序应该可以实现基于属性的分片

一个多层次的关联对象(multi-level object graph)通过 Hibernate 级联功
能存储时,ShardSelectionStrategy 只会在存储顶层对象考虑,所有子对象(children objects)将会自动的存储在和父对象(parent)相同的片段上
如果你不希望你的模型(model)有这个限制,那么很好,只要记住,你在做基于属性的分片(shard)选择,你所使用的用来做决定的属性必须在传递给 session.save()时的每个对象里得到。


ShardResolutionStrategy
解析出一个指定 id 对象在哪个片段集合(set of shards)
ShardResolutionStrategy 是管理实体(entity)名字/标识符(id)映射片段(shard)缓存(cache)的绝好地方。

标识符生成(ID Generation)对片段选取(Shard Resolution)影响很大。如果你为你的类选择一个标识符生成器(ID Generation),把 shard id 编码在对象的标识符(id)内,你的ShardResolutionStrategy 将永远不会被调用。如果你计划只使用把 shard id 编码在你的对象的标识符(ids) 里的标识符生成器(ID generators) 你应当使用 AllShardsShardResolutionStrategy ,作为你的 ShardResolutionStrategy。

片段选取(Shard Resolution)对标识符生成(ID Generation)影响很大,片段选取(shard ,有两种方式实现这resolution)的目的是找到一个指定标识符对象所在的存储片段(shard)个目的:
     使用 ShardResolutionStrategy,上述。
     在生成标识符(ID)时把 shard ID 编码到对象的标识符(ID)上,并在片段选取(shardresolution)时检索 Shard ID。

把 shard ID 编码到对象标识符(ID)的主要优点是它能够使 Hibernate Shards 能够更快的从而不需要数据库查询,缓存查询,等等。
对象标识符选取片段(resolve shard)                                   Hibernate Shards
不需要任何特殊编码/解码的 shard ID 算法——所有你需要做的是使用一个标识符生成器
(ID Generator)实现 ShardEncodingIdentifierGenerator 接口。Hibernate Shards 所包含的两个标识符生成器(ID generators),ShardedUUIDGenerator 实现了该接口。



ID Generation

1.Native ID 生成策略
2.配置你的数据库来避免标识符(IDs)冲突
3.应用程序级别的 UUID
4.分布式 hilo 生成器



二次分片
虚拟片段(Virtual Shards)
为了能够使用虚拟分片(virtual sharding),你需要使用从虚拟的 shard ids 到物理 shard ids为了能够使用虚拟分片(virtual sharding)映射的 Map 来创建你的 ShardedConfiguration,这里我们有 4 个虚拟片段(virtual shards)映射 2 个物理片段(physical shards)的示例:

Map<Integer, Integer> virtualShardMap = new HashMap<Integer,Integer>();
virtualShardMap.put(0, 0);
virtualShardMap.put(1, 0);
virtualShardMap.put(2, 1);
virtualShardMap.put(3, 1);
ShardedConfiguration shardedConfig =
     new ShardedConfiguration(
          prototypeConfiguration,
          configurations,
          strategyFactory,
          virtualShardMap);
return shardedConfig.buildShardedSessionFactory();



为了在以后改变虚拟片段到物理片段的映射,只需要改变传递到这个构造器的virtualShardToShardMap 。

查询(Querying)
限制
1.order-by 子句
2.Distinct 子句
aggregation 工作的很好

HQL
为 HQL 的支持,在这点上,并没有像 Criteria 查询那样有良好的支持,我们甚至没有
实现任何一个查询解析的扩展,所以我们不支持 distinct、order-by 和 aggregation,即就是你.只能使用 HQL 进行简单的查询,你最好能够在这次发布中清除所有的 HQL 除非你能想到办法。



查询时使用分片策略(Shard Strategy)
你的当执行查询(Criteria 或者 HQL)所参考的分片策略(shard strategy)的唯一组成部分是 ShardAccessStrategy
ShardSelectionStrategy 被忽略了是因为执行一次查询不需要在数据
库创建任何新的记录;ShardResolutionStrategy 被忽略的因为目前我们假设你总是希望在所有的片段(Shards)上执行你的查询。


如果情况并不是这样,那么最好把 Session 向下强制类型转化(downcast)成一个 ShardedSession,并 找出你要的特定分片(shard-specific)的SessionS。虽然有点笨,但是它起作用,在以后的发布我们为其会有一个更好的解决方案。


未完成的Hibernate API实现

跨片段的关联对象(Cross-Shard Object Graphs)
当 A 对象和 B 对象在不同的片段(shards)上时,创建一个 A 和 B 的关联是非
法的。在某些应用程序里,你的 model 对象以这种方式构造是很难犯这种错误
Hibernate 将会认为是列表里的“糟糕的(bad)”对象,并假定你启用了级联这种关系,它将在不同片段(shard)上创建这个对象的新版本,这会出现问题。为了帮助防止这种事情发生,我们使用了一个在所有创建 或 保 存 的 对 象 时 检 查 跨 片 段 ( cross-shard ) 的 关 系 的 拦 截 器 ( interceptor ) 命 名 为CrossShardRelationshipDetectingInterceptor 。

不幸的是,使用 CrossShardRelationshipDetectingInterceptor 是有代价的,为了决定一个关联的对象在哪个片段(shard)上,我们需要从数据库获得这个对象,所以你如果使用延迟加载(lazy-loaded)关联,拦截器将会把查询这些关联关系作为其检查的一部分。这种代价可能 是 相 当 昂 贵 的 , 可 能 不 适 合 产 品 系 统 。 考 虑 到 这 点 , 我 们 通 过hibernate.shard.enable_cross_shard_relationship_checks 属性(参考配置章节)来简单地配置是否 需 要 执 行 检 查 , 如 果 此 属 性 设 为 true , 在 建 立 每 个 ShardedSession 会 话 的 时 候CrossShardRelationshipDetectingInterceptor 对象都会被注册。别担心,你也能注册自己的拦截器。我们希望大多数应用在 dev 和 qa 环境时将会启用这个检查,而在分段(staging)、负载(load)、性能测试(perfomance),生产(production)环境禁止。


分布式事务

Hibernate Shards 在一个非容器托管(non-managed)的环境里不提供分布式事务的支持,如果你的应用程序需要分布式事务,你需要插入一个支持分布式事务的事务管理实现(transaction management implementation)。


有状态的拦截器(Stateful Interceptors)


深层次的原因是,我们为每一个片段(shard)  初始化一个org.hibernate.SessionImpl。如果我们希望一个拦截器(Interceptor)关联到一个会话(Session) ,那么我们在 ShardedSession 被创建时,需要传递所有提供的拦截器(Interceptor)
可以选择由 StatefulInterceptorFactory 构造的拦截器(Interceptor)
的类型实现 RequiresSession 这个接口的。一旦工厂构造它的时候,Hibernate Shards 将会提
供指向真正的(指定片段的(shard-specific))会话(Session)的拦截器(Interceptor)。这样,你的拦截器(Interceptor)能够安全,准确地和特定的片段(shard)交互



冗余数据(Replicated Data)
尽管这是一个水平分片的框架,但在每个片段(Shard)上,几乎总是存在一些只读(至少
是很少改变的)的数据,如果你只是读取这些数据,我们不会有问题的,但是如果你希望通
过分片的实体关联这些实体,我们就有麻烦。假如你在每一个片段(Shard)上有一个数据
完 全 相 同 的 国 家 表 , 假 定 WeatherReport 有 一 个 Country 成 员 , 我 们 怎 么 保 证 那 个WeatherReport 关联的 Country 和 WeatherReport 是在同一个片段(shard)上。我们有很多想法来让这个问题容易处理,但是我们还没有任何实现。从短期来看,我们认为你最好的选择是也不要创建分片实体和冗余实体之间的关联。换句话说,   如果你不使用建模工具,选择你会的方式为关系建模。我们知道这个有点笨和讨厌,我们会马上解决它。



从美学角度来看,这个实现并不太好.代码何必关心放到哪个数据库.不到万不得已的数据量,还是 mysql proxy来的透明,轻松实现也快,关键是我不需要写额外的代码.来自一个懒得写代码的程序员

你可能感兴趣的:(mysql,算法,框架,Hibernate,配置管理)