首页 > Space导入, 技术 > 多数据库SaaS尝试

多数据库SaaS尝试

    手上的APIS要上SaaS,其实就是ASP(Application Service Provider)。要求一份程序,一或多份数据库跑服务。设计的时候参考了阿里软件人写的《互联网时代的软件革命-SaaS架构设计》。这本书从广度上覆盖了做SaaS的很多内容,但深度却显不足,很多地方只是浅尝辄止,一笔带过。

    虽然如此,作为算是这个领域的第一本入门书,还是有一些参考价值的。比如,定义了SaaS四个成熟度模型:定制开发、可配置、高性能的多租户架构、可伸缩的多租户架构;APIS只有一个运行实例,但租户数量不会很多,短期内不会超过50,所以算入第3级,高性能的多租户架构。

    在数据库设计上,这本书对SaaS应用,提供了四个可选方案。独立数据库、共享数据库+隔离数据架构(Schema)、共享数据库+共享数据架构(Schema)。由于采用了MySQL,没有schema的概念,所以去掉了中间的选项。虽然技术人员有上高精尖技术的冲动,不过鉴于我们的用户数不会很多,用户和用户之间也完全隔离,采用了第一种方案。而这种方案,对开发其他功能完全没有任何影响,算是非常unobstructive(中文不好翻译,一般叫“无侵入”)的方案。只要在入口的Filter留个ThreadLocal标志,最底层的SessionFactory做个拦截,功能上算是搞定了。大概就是事先准备好几个SessionFactory,然后哪个用户上来了就给谁相应的SessionFactory。

    但革命的道路是曲折的,过程是漫长的。虽然前期通过阅读Spring代码做过一些技术调查,但Spring+Hibernate这对组合的复杂性还是折腾我老半天。Spring对Hibernate支持很好,几乎是全方位的,这也造成了我要到处扩展用到的Spring支持类。本来只打算对LocalSessionFactoryBean动手,却忘了spring大部分的Bean都是singleton,但又舍不得换成prototype后的性能下降,于是抡起袖子又扩展了BasicDataSource(DBCP)、HibernateTemplate、HibernateDaoSupport、HibernateTransactionManager。好不容易有点眉目,开始从配置的租户数据库载入数据,却屡屡抛session提前关闭的异常。而且诡异的是,这个异常出现的概率约为75%,而一旦我用Debug跟进去后,反而基本不抛异常了。这让我异常胸闷,要知道这种问题十有八九是并发的原因,这问题找起来很头大,往往陷入Spring+Hibernate的汪洋大海。

    接下来几天感冒发烧,好好休息了一阵子,思路却打开了。从网上重新搜出一堆资料。这个是Stack Overflow的一个问答,几个回答都比较靠谱;这个是通过HotSwappableTargetSource提供的DataSource动态替换;这个是Spring开发人员利用AbstractRoutingDataSource提供对DataSource的路由。权衡再三,决定使用AbstractRoutingDataSource。只扩展了两个类就成功实现功能,不抛异常。全局一个SessionFactory,后面几个DataSource轮流上。

    但问题又来了。二级缓存这个东西和SessionFactory绑定,多个DataSource要求要多个Cache,因为各个租户之间的数据主键很可能重复。我试图搜寻通过改造SessionFactory的CacheProvider来搞定,但未果,SessionFactory的Cache埋得有点深。

   最后,参考了这篇这篇,用一个简单的Decorator,退回了多SessionFactory,虽然代码不是很好看,但再无异常。今天收工。

分类: Space导入, 技术 标签: ,
  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word


Warning: fsockopen() has been disabled for security reasons in /home/onlymars/public_html/wp/wp-includes/class-snoopy.php on line 1148