在Redis中快速插入5000万条记录的方法

时间:2019-06-17 04:50:40

标签: c# redis

我有一个大约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]);
                    }
                }

2 个答案:

答案 0 :(得分:3)

您的代码有几个问题,您可以对其进行优化以使其运行更快。

对Redis的请求太多。

如果键不存在,那么对于每个记录,您都会向Redis发送2个请求。如果密钥已经存在,那么对于每个记录,您都会向Redis发送3个请求。因此,对于5000万条记录,您向Redis发送了100-1.5亿个请求。会有很多往返时间。这样会很慢。

相反,您可以将代码包装到Lua script中,并且对于每条记录,仅向Redis发送一次请求。

此外,您的代码不是原子的。如果有多个客户端向Redis发送请求,则代码将中断。但是,使用Lua脚本,可以确保代码是原子的,以便可以进行秒优化。

增加并发性

似乎您通过单个线程/进程将请求发送到Redis。 Redis很快,但是您的客户端太慢。因此,您可以将记录分为几个部分。对于每个部分,创建一个新线程以将请求发送到Redis。当然,您必须确保代码是线程安全的,请检查第一个优化。

减少记录数

在您的示例中,您的记录具有许多重复的MD5和不同的ID。对Redis的这么多请求是无操作的,因为它们将被后续请求覆盖。因此,您可以进行(外部)排序,并在向Redis发送请求之前删除这些重复项。

答案 1 :(得分:0)

您需要使用--pipe命令

首先,创建一个包含以下格式的所有数据的文件,并将其另存为data.txt

SET Key0 Value0
SET Key1 Value1
...
SET KeyN ValueN

之后,您可以运行--pipe命令

cat data.txt | redis-cli --pipe

有关详细信息,Redis Mass Insertation