论坛首页 Java企业应用论坛

freyja v2版本发布

浏览 2007 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2012-05-28   最后修改:2012-05-28

上回说了

freyja将重新把重心放在orm、sharding、cache上

 

1、更完善的orm

2、应用层屏蔽的底层sharding

3、应用层上的cache

那么,直接上代码了。

 

 

因为没什么开源经验,所以直接介绍freyja的思想和代码了。

1、cache部分直接改的是spring aop cache

 

spring cache 拓展 

加了几个annotation:

CacheDelete、CacheListReplace 等等。。。。

现在存在2个问题:1、不是线程安全的。2、不知道如何才能像spring 的cache 注解那样 被扫描到:http://www.iteye.com/problems/83419

 

 

另外:cache和freyja v2没有任何关系。

cache的介绍有点少,缓存越接近上层效率越高。所以基本上放弃了freyja v1对缓存的理解,改到上层缓存。

通过注解维护缓存的关系。上面的spring cache 拓展实际上是之前写的,现由对其进行了大改。山寨、拓展了spring 自带cache 同样使用spel表达式 CacheSave这个注解略微不同,key取值取的是返回值,以后会补上一篇介绍。

 

 

 

2、orm

orm部分采用自己的annotation:@Id,@Column,@Table,@Transient 用这几个来标注实体与表的关系

 

orm比纯jdbc带来的开销在于一层的sql解析,sql解析交给了温少的alibaba.druid的sql parser部分来处理。

(温少是谁?:http://code.alibabatech.com/wiki/dashboard.action)

解析的效率很高,具体有多高我没具体测试过。以为无论开销多大对于项目来说是属于可忽略的开销,因为项目的sql都是预编译sql,解析这一层被缓存了所以开销可忽略。

 

orm的语法上和上一版的基本一致。

 

3、sharding

Freyja2版本对分库分表的处理方式 

 

sharding部分和orm基本上没任何关系,这个部分只针对纯sql 的处理。我觉得freyja的sharding方式趋于完美

freyja v2的sharding 由@SubColumn决定分库、分表方式。@SubColumn是以这个字段为基准对记录进行切分

 

	public DbResult getShardingTableName(Object value) {
		String tableName = getTableName();

		int hashCode = value.hashCode();
		if (hashCode < 0) {
			hashCode = -hashCode;
		}
		int dbNo = hashCode % ShardingUtil.engine.getDbNum();
		int tableNo = hashCode % ShardingUtil.engine.getTableNum();
		tableName = tableName + "_" + tableNo;
		return new DbResult(tableName, tableNo, dbNo);
	}

	public DbResult getShardingTableNameById(Object idValue) {
		String tableName = getTableName();
		if (idValue == null || !isSubTable()) {
			return new DbResult(tableName, -1, -1);
		} else {
			int n = (Integer) idValue / ShardingUtil.engine.getIdSubNum();
			int dbNo = n / ShardingUtil.engine.getTableNum();
			int tableNo = n % ShardingUtil.engine.getTableNum();
			tableName = tableName + "_" + tableNo;
			return new DbResult(tableName, tableNo, dbNo);
		}

	}
 

 

 

配合spring jdbc的AbstractRoutingDataSource 达到一个多数据源操作环境

 

具体而言如果你需要对t_user表进行分库、分表操作:

1、 <bean id="fryjaTemplate" class="org.freyja.v2.jdbc.FreyjaJdbcTemplate">

		<property name="jdbcTemplate" ref="jdbcTemplate" />
		<property name="packagesToScan" value="com.x.data.bean" />
		<property name="freyjaProperties">
			<value>
				show_sql=true
				db_num=2
				table_num=2
				id_sub_num=1000000
			</value>
		</property>
	</bean>

 

 配置 db_num、table_num、id_sub_num

id_sub_num为每张表容量,另外建表的时候需要修改对应的自动增长起始值

 

 

	<bean id="baseDataSource" parent="parentDataSource">
		<property name="url" value="${mysql.url}" />
		<property name="username" value="${mysql.user}" />
		<property name="password" value="${mysql.password}" />
	</bean>

	<bean id="dataSource" class="com.guyu.core.spring.datasource.DynamicDataSource">
		<property name="targetDataSources">
			<map key-type="java.lang.Integer">
				<entry key="0" value-ref="pu_game_0" />
				<entry key="1" value-ref="pu_game_1" />
			</map>
		</property>
		<property name="defaultTargetDataSource" ref="baseDataSource" />
	</bean>
 

 

	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource" />
	</bean>
 

 

2、你需要在User实体上加上@Table(name = "t_user", isSubTable = true)

 标注这个表需要切分

3、 @Column(name = "open_id")

@SubColumn(isSubColumn = true)
private String openId;
 

需要选取其中一个字段标注为SubColumn

 

 

sharding针对的是纯jdbc,有兴趣的可以研究下druid的sql parser (ps:资料很少)

 

其他的补充:

1、为什么freyja1和2都要用spring jdbc?

没什么特别的理由,一直都在用hibernate但先接触的spring jdbc,觉得还不错就用了。另外spring jdbc本身就很接近于orm所以就对他进行了改造。

2、druid

在做freyja v1的时候实际上都有了解过druid的sql parser功能,但是觉得老外的jsqlparser出来得早用的人多会比较好就用了jsqlparser。

后来做v2发展sharding功能的时候联系到了温少,他让我看sql parser。结果真不得了。sql parser要什么有什么,例如orm部分sql parser直接就支持而且非常方便。虽然有点问题但是反馈给温少之后一会儿就解决了。sharding功能也是在交流过程中产生的。

附件中的压缩包中的druid_0.2.11111.jar是包含sharding支持的版本。druid的最新版不知道有没有发布包含这个部分。

 

还需要大量的测试测试测试和测试,现在freyja v2用于项目当用,有什么需要修复和添加的功能都会随着实际应用而改动。

 

3、提供了一个注解Async

public @interface Async {

	boolean saveAsync() default false;

	boolean updateAsync() default false;
}

 这个注解用于异步save和update。如果cache已经覆盖了数据层,是可以把数据操作异步化。尤其是哪些不重要的数据和不需要返回的日志数据等。。。。

@Table(name = "t_user", isSubTable = true)
@Async(saveAsync = false, updateAsync = true)
public class User{
}
 这个注解目前没和freyja的操作联系起来。

 

 

 

希望大家就cache、orm、sharding部分的实现思路进行讨论!

   发表时间:2012-05-28   最后修改:2012-05-28
针对数据迁移说麻烦也不麻烦,不麻烦也麻烦。。。
方法就是舍弃id字段把数据针对subColomn 进行重新分配库、表、id
这个操作应该只能使用程序实现,也许我会再freyja里面提供这种方法!

说到这里,我发现实际上如果你是从1个库、表 需要重新分配到多个库、表
直接copy一套bean。
例如你有一个 User 对于 t_user 表 User注解配置为
@Table(name="t_user",subTable =false)
你可以再建立一个 UserCopy 对象 对应t_user_copy注解配置为 @Table(name="t_user_copy",subTable =true) 然后需要做的事情就是 把 User查询出来 然后 save(UserCopy) 就行了~~~~

然后原本的数据就会存在于分库之后的库、表里面

有一点需要注意:subColumn如果是关联与其他表的字段
例如有一个t_user uid字段,另外一个表t_user_property uid pid num
t_user_property的uid是外键关联与t_user表的uid这个时候 save的时候需要改动了!
具体办法我会再出一篇具体实现
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics