论坛首页 Java企业应用论坛

我也想了一个循环流水号实现,同时考虑集群环境与高并发

浏览 4684 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-09-19  
第一次发帖,发现还需要做一个发帖小测试,满有意思的!好了进入正题!
刚才看http://www.iteye.com/topic/1114846 做了一个循环流水号的实现,实际上我最近也遇到的关于流水号的需求,觉得他的实现太过于简单.这里说说我的实现想法,请大家点评,欢迎拍砖!

首先: 流水号通常是唯一的如果重启后如何保证流程号的连续性.
其次: 没有考虑集群环境,在多机部署的情况下没有同步流水号会出来流水号重复现象.
再次: 高并发访问,既是我们通过数据库来记录流程号,如用Oracle的sequence频繁的数据访问会造出很大的IO效率问题,同时事务问题也不好控制.

这里我就想了一个实现是这样的.
首要解决的事高并发和重启后保证流水号不连续性问题.
我们在数据库中存放流水号的生成规则如(流水号格式,流水号缓存大小,流水号重置规则),以及当前流水号的最大值.
采用单实例每一类流水号生成唯一的流水号提供服务类.按照流水号缓存大小一次性加载需要缓存的流水号到内存中.
仅当消费的流水号超过了内存中最大的缓存数时,才向数据库中写入前流水号的最大值.并且再次一次性生成缓存值大小的流水号到内存中或者当服务器关闭时也写入写入前流水号的最大值.
这样做的目的仅仅是解决了高并发访问效率问题,减少了数据读写的操作,如当我设置缓存值为500时,只有当缓存中所有的流水都被消费完了,才会一次性再向数据库申请500个流水号.

但是这样做还不能解决集群问题,由于集群下每个JVM虚拟机拥有自己独立的实例,那么单实例每一类流水号生成唯一的流水号提供服务类互相之间还要解决同步问题,可以通用ehcache的集群同步机制, 将流水号服务类交给ehcache管理.
保证在各个集群下不同JVM拥有相同的流水号提供服务类.解决流水号重复现象.
   发表时间:2011-09-20  
nicowyh 写道
如用Oracle的sequence频繁的数据访问会造出很大的IO效率问题,同时事务问题也不好控制.

IO问题是应该考虑的。但事务问题,没想明白,楼主可否举例明说。

nicowyh 写道
这里我就想了一个实现是这样的.
首要解决的事高并发和重启后保证流水号不连续性问题.
我们在数据库中存放流水号的生成规则如(流水号格式,流水号缓存大小,流水号重置规则),以及当前流水号的最大值.
采用单实例每一类流水号生成唯一的流水号提供服务类.按照流水号缓存大小一次性加载需要缓存的流水号到内存中.
仅当消费的流水号超过了内存中最大的缓存数时,才向数据库中写入前流水号的最大值.并且再次一次性生成缓存值大小的流水号到内存中或者当服务器关闭时也写入写入前流水号的最大值.
这样做的目的仅仅是解决了高并发访问效率问题,减少了数据读写的操作,如当我设置缓存值为500时,只有当缓存中所有的流水都被消费完了,才会一次性再向数据库申请500个流水号.

我觉得这个思路是可以采纳的,有一定可行性。

nicowyh 写道
但是这样做还不能解决集群问题,由于集群下每个JVM虚拟机拥有自己独立的实例,那么单实例每一类流水号生成唯一的流水号提供服务类互相之间还要解决同步问题,可以通用ehcache的集群同步机制, 将流水号服务类交给ehcache管理.保证在各个集群下不同JVM拥有相同的流水号提供服务类.解决流水号重复现象.

这里面如何实现,楼主能否详细说明一下?学习学习
0 请登录后投票
   发表时间:2011-09-22  
nicowyh 写道
第一次发帖,发现还需要做一个发帖小测试,满有意思的!好了进入正题!


这里我就想了一个实现是这样的.
首要解决的事高并发和重启后保证流水号不连续性问题.
我们在数据库中存放流水号的生成规则如(流水号格式,流水号缓存大小,流水号重置规则),以及当前流水号的最大值.
采用单实例每一类流水号生成唯一的流水号提供服务类.按照流水号缓存大小一次性加载需要缓存的流水号到内存中.
仅当消费的流水号超过了内存中最大的缓存数时,才向数据库中写入前流水号的最大值.并且再次一次性生成缓存值大小的流水号到内存中或者当服务器关闭时也写入写入前流水号的最大值.
这样做的目的仅仅是解决了高并发访问效率问题,减少了数据读写的操作,如当我设置缓存值为500时,只有当缓存中所有的流水都被消费完了,才会一次性再向数据库申请500个流水号.


集群不需要这么麻烦的,其实这种情况就可以应用到集群中的。
利用版本号来解决并发数据不一致问题。


伪代码:

single{
int currentValu;
int maxValu;

init(){

int currentValue=db.currentValue;
int maxValue=db.maxValue;
}

getValue(){

if(currentValue-1==maxValue){
     currentValue=db.currentValue;
     maxValue=db.maxValue;
}

return currentValue++;

}

}

0 请登录后投票
   发表时间:2011-09-22  
差不多的思路,稍微调整一下
const int batch_size = 1000;
long current=0;
long max=0;
synchronized long next()
{
    if(current >= max)
    {
        transaction{
            update set db.next_id = db.next_id + batch_size;
            current = db.next_id;
            max = current + batch_size;
        }
    }
    return current++;

}
0 请登录后投票
论坛首页 Java企业应用版

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