我正在使用aws sqs队列。队列可能有大量的消息,也就是说,如果我不处理,每小时将有超过一百万个消息。
我正在处理所有消息,并将它们放入mysql表中。Innodb有22列。在重复密钥更新时插入。我有一个主键和一个唯一键。
我正在使用C#,我运行了80个线程,以便从SQS拉取消息。
我在c#中应用了事务,同时在c#中使用锁,从而只有一个线程可以更新表,同时运行查询"insert on duplicate key update“。如果id不使用mysql锁,则发生C#死锁时会抛出异常。
问题出在这里,我可以看到在C#锁之前有很多线程在等待,而且这个时间逐渐增加。有谁能建议我做这件事最好的方法是什么?
注意,我有8 8GB内存,英特尔至强2.53,1GE网速。请在这方面给我提个建议。
发布于 2015-11-15 04:43:28
如果我这样做,C#程序将主要创建CSV文件来清空您的SQS队列。或者至少是其中的一大部分。然后,该文件将用于大容量插入到一个空的非索引工作表中。我会选择非临时性的,但不管怎样。当这种情况反复发生时,我认为没有理由将temporary添加到混合中,并且当完成时,工作表无论如何都会被截断。
大容量插入将通过从c#程序发出的LOAD DATA FROM INFILE来实现。或者,可以使用递增器写入其他表中新行中的值,表示file2已准备好,file3已准备好,并且LOAD在触发的事件中发生,例如每n分钟。与mysql创建事件放在一起的事件。一个中的六个,另一个的六个。
但是,前哨互斥的好处可能是有价值的,因为整个事情是分批发生的。并且在此发生时需要暂停要处理的下一批(Es)。让我们称其为概念行,正在处理的是The Blocker N。
好了,现在你的数据已经在工作表中了。在处理之前,它是安全的,不被践踏。假设你有25万行。其他批次很快就会跟进。如果要进行特殊处理,您可能希望创建索引。但目前还没有。
您可以使用此工作表对实际表执行普通的insert on duplicate key update (IODKU)。在IODKU中,它将遵循正常insert into select模式,其中select部分来自工作表。
在该语句的末尾,工作表被截断,所有索引被删除,行N的状态设置为complete,当出现行N+1时,The Blocker可以自由地处理它。
删除索引是为了便于下一轮大容量插入,在下一轮大容量插入中,维护索引是最不重要的。在IODKU期间,工作台上的索引很可能是不必要的开销负担。
通过这种方式,你可以两全其美。
而焦点被从多线程上转移了,这是一件很好的事情,可以把人们的注意力从多线程上移开。
这里有一篇关于性能和策略的很好的文章,标题是Testing the Fastest Way to Import a Table into MySQL。不要让mysql版本的标题或文章中的内容吓跑你。跳到底部,并获得一些结论:
在不使用raw文件的情况下,将表导入到MySQL中的最快方法是LOAD DATA语法。将并行化用于InnoDB以获得更好的结果,并记住调优基本参数,如事务日志大小和缓冲池。仔细的编程和导入可以使一个>2小时的问题变成2分钟的过程。您可以暂时禁用某些安全功能,以获得额外的性能
出于几个原因,我会将C#例程与实际的加载数据和IODKU更新工作完全分开,并将其留给Create event中提到的事件。主要是更好的设计。因此,C#程序只处理SQS,并写出带有递增文件号的文件。
https://stackoverflow.com/questions/33712319
复制相似问题