日期:2014-05-17  浏览次数:20667 次

java分布多台服务器,怎么做到同步操作
有个功能大致如下,在一堆没用过的数据中取一条数据,并将其标示为已用,原来是只有一台服务器,在获取并修改状态的方法上加上synchronized就可以,现在要分布部署为多台服务器,会不会出现并发读取到同一条数据的问题,要怎么解决,谢谢。
------解决方案--------------------
在一堆没用过的数据中取一条数据,并将其标示为已用, 这个方法抽取出来, 供所有集群机器调用
------解决方案--------------------
对,简单的做法就是HTTP请求(这个请求需要同步,保证ID不会被多次获取),获取一系列ID,然后通过ID,去获取对应的数据,保证唯一。

还有的方法是: 对ID进行策略分片,如: 1 2 3 4 5 个机器,他们只能获取到之后以为是对应的ID 
 机器1(可以是IP),它只能获取xxxxx1的ID。。。。以此类推

------解决方案--------------------
就是分布式系统处理一致性的问题罗,没处理过,我就不百度转贴了。
------解决方案--------------------
类似一楼说的,你的数据是分布式的,但抽取数据这个方法是共通的就行
------解决方案--------------------
使用数据在多台机器进行,取数据只在一台机器上进行
------解决方案--------------------
把这一堆没用的数据放在分布式的缓存系统中,如JCS。那么在其中一台计算机上修改了其中一个数据的状态,过一会儿,这个数据就会同步到所有其他计算机上了。
在分布式的系统中,其他计算机读到同一条还没来得及更新的数据,这应该是没办法的。所以分布式应用的第一原则就是不用分布式系统。
------解决方案--------------------
楼主应该是指从数据库从取数据吧?如果从数据库中取数据,可以利用数据库的事务控制来处理。
处理过程分为三个步骤:
1、从数据库查询一条状态为为用的记录(不同的数据库写法会不一样)
select * from table1 where state = '未用' limit 1

2、将数据状态更新为已用,如果更新成功(影响记录数为1表示成功)则表示获取数据成功,否则这条数据已经被其他服务器或线程所抢用。
update table1 set state = '已用' where id='数据id' state = '未用';
 
3、使用数据,如果未正常使用数据可将数据状态还原为未用

上面这个方法存在一个缺陷,假如获取数据后本服务器挂掉,会导致数据未正常处理,可以考虑另外一个方法处理。
增加一个用于记录数据获取的表table2(table1_id(主键),guid(用于唯一标识获取数据放),expired(过期时间))。
1、从数据库查询一条状态为为用的记录,不同的数据库写法会不一样
delete from table2 where expired <= '当前时间';(先删除过期的记录,可能获取方已挂掉)
select * from table1 where state = '未用' and not exists(select * from table2 where table1_id = table1.id) limit 1;

2、在table2插入一条数据表名本方已获取数据,如果插入成功(影响记录数为1,没有抛出主键冲突的异常)则表示获取数据成功,否则这条数据已经被其他服务器或线程所抢用。
insert into table2 (...) values (记录的id,本方的唯一标识,当前时间+一个合理的值作为过期时间);
  
3、使用数据,如果正常使用数据则将数据状态更新为已用,并删除table2的记录
update table1 set state = '已用' where id='数据id' state = '未用';
delete from table2 where id=[id];

上面是本人的实现思路,仅供参考。