我有一个大约 10 GB 的文本文件,包含 5000 万行。对于文件中的每一行,如果记录不存在,我将插入该记录,否则比较现有记录的 ID 和当前行 ID,如果当前 ID 小于记录 ID,则更新.
目前,插入/比较记录需要大约 8 个小时
文本文件中的示例数据:
Md5,Id
d41d8cd98f00b204e9800998ecf8427e,1000
e358efa489f58062f10dd7316b65649e,1001
626726e60bd1215f36719a308a25b798,1002
d41d8cd98f00b204e9800998ecf8427e,5002
d41d8cd98f00b204e9800998ecf8427e,0953
626726e60bd1215f36719a308a25b798,0152
我尝试过实现生产者/消费者模式,但生产者会太快并消耗大量内存,从而导致 OutOfMemory 异常。
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");
IDatabase db = redis.GetDatabase();
int lineCount = 0;
foreach(var f in File.ReadLines(@"big_text_file.txt").Skip(1))
{
lineCount++;
string[] lines = null;
lines = f.Split(",")
if (!db.KeyExists(lines[2]))
{
db.StringSet(lines[2], lines[0]);
}else //contains key
{
var keypair = db.StringGet(lines[2]);
if(Convert.ToInt32(lines[0]) < Convert.ToInt32(keypair))
{
db.StringSet(lines[2], lines[0]);
}
}
最佳答案
您的代码有几个问题,您可以优化它们以使其运行得更快。
对 Redis 的请求过多。
如果键不存在,对于每条记录,您向 Redis 发送 2 个请求。如果 key 已经存在,则对于每条记录,您向 Redis 发送 3 个请求。因此,对于 5000 万条记录,您向 Redis 发送 100 - 1.5 亿个请求。会有很多往返时间。所以会很慢。
相反,您可以将代码包装到 Lua script 中,并且对于每条记录,只向 Redis 发送一次请求。
此外,您的代码不是原子的。如果有多个客户端向 Redis 发送请求,您的代码就会中断。但是,使用 Lua 脚本,您可以确保代码是原子的,这样您就可以进行秒级优化。
增加并发
您似乎使用单个线程/进程向 Redis 发送请求。 Redis 非常快,但是,您的客户端太慢了。所以你可以把你的记录分成几个部分。对于每个部分,创建一个新线程来向 Redis 发送请求。当然,你必须确保你的代码是线程安全的,检查第一个优化。
减少记录数
从你的例子来看,你的记录有很多重复的 MD5 和不同的 ID。对 Redis 的如此多的请求是空操作,因为它们将被后续请求覆盖。因此,您可以进行(外部)排序,并在向 Redis 发送请求之前删除这些重复项。
关于c# - Redis快速插入5000万条记录的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56624879/