多线程程序中的数据不一致

时间:2015-05-08 14:52:15

标签: java multithreading parallel-processing apache-storm

我在使用多线程编程时遇到数据一致性问题。

用例:我将在队列中获取消息(人员信息)。我有一个多线程代码,它从队列中获取数据并将其放入另一个数据库。在这里,我需要比较人员信息,如果有任何重复,我需要合并/更新并将其插入另一个数据库。

问题:如果两个相似的人物对象同时位于两个不同的线程中,则两者都会对待此人,因为它在第二个数据库中不存在并且都试图插入它 - 所以这里我们会有重复的记录。

如何解决上述问题?

  

从概念上讲,如果我知道该怎么做,我可以用Java编写代码,或者使用Apache风暴并运行并行进程。

3 个答案:

答案 0 :(得分:1)

可能的解决方案:

  1. 当您插入队列时检查重复项。维护队列之外的哈希表。每次插入队列时,都要检查数据是否已经在哈希表中。如果是这样,丢弃插入物。插入的复杂性仍然是O(1),但增加了内存成本。

  2. 不是插入单个队列,而是根据哈希值插入多个队列。一个消费者线程处理一个队列。这也是维护时间序列数据的常用方法。

答案 1 :(得分:0)

我很久以前就编写了一个简单的锁定机制来锁定对象的值而不是实例。它有点慢,但是如果你在两个线程上都有一些相同的键可能会有效。

is.binary=function(filename) {
  is_binary=TRUE
  #suppress warnings and try to read file with binary reader
  #if it throws an error, set is_binary to FALSE
  withCallingHandlers(expr=tryCatch(load(filename),
                                    error=function(err) is_binary<<-FALSE),
                      warning=function(w) invokeRestart("muffleWarning"))
  #since R loads the objects of the binary file into the memory, delete them
  #maybe this is unnecessary ... 
  #... I do not know how R handles memory of objects that go out of scope
  rm(list=ls()[ls()!="is_binary"])
  is_binary
}

答案 2 :(得分:0)

如果您使用的数据库支持事务和事务隔离,则可以依赖它。您可能需要使用Serializable隔离级别来避免Phantom Reads。每个验证+更新/插入操作都应在单个事务中执行。

<强>说明: 您描述的问题是一种并发效应。它被称为Phantom Reads。想象一下,首先检查数据库表是否已包含名字为#34; test&#34;通过使用选择查询。查询返回空结果集。因此,您决定将此人员插入数据库。同时,在您发出select查询之后但在发出插入查询之前,另一个线程正在尝试执行相同的操作,即检查数据库是否包含名称为&#34; test&#34;的人员。第二个线程将人员插入数据库。如果第一个线程在执行插入后发出相同的select查询,并观察到有2行而不是预期的1(它刚刚插入),那就是幻像读取。您可以在此维基百科文章Isolation (database systems)

中阅读有关隔离和并发效果的更多信息

如果您的数据库不支持事务或Serializable隔离级别,则需要自己进行同步。如果所有线程都在单个JVM中,则可以使用synchronized关键字或ReentrantReadWriteLock。如果线程在不同的JVM中,您可以使用分布式锁服务(Terracotta或Hazelcast)。