Быстрый способ вставить 50 миллионов записей в Redis - PullRequest
0 голосов
/ 17 июня 2019

У меня есть текстовый файл размером около 10 ГБ, содержащий 50 миллионов строк.Для каждой строки в файле я вставляю запись, если она еще не существует, в противном случае сделайте сравнение с идентификатором существующей записи и текущим идентификатором строки и обновите, если текущий идентификатор меньше идентификатора записи.

В настоящее время вставка / сравнение записей занимает около 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 ]

3 голосов
/ 17 июня 2019

У вашего кода есть несколько проблем, вы можете оптимизировать их, чтобы он работал намного быстрее.

Слишком много запросов к Redis.

Если ключ не существует, для каждой записи,Вы отправляете 2 запроса в Redis.Если ключ уже существует, для каждой записи вы отправляете 3 запроса в Redis.Таким образом, для 50 миллионов записей вы отправляете 100-150 миллионов запросов в RedisТам будет много времени туда и обратно.Так что это будет очень медленно.

Вместо этого вы можете заключить свой код в Lua-скрипт , и для каждой записи отправлять запрос в Redis только один раз.

ТакжеВы код не атомарный.Если в Redis отправлено более одного клиента, ваш код нарушается.Тем не менее, с помощью сценариев Lua вы можете убедиться, что код является атомарным, что позволяет оптимизировать секунды.

Повышение параллелизма

Похоже, что вы отправляете запрос в Redis с помощью одного потока/процесс.Redis очень быстрый, однако ваш клиент работает слишком медленно.Таким образом, вы можете разделить свои записи на несколько частей.Для каждой части создайте новый поток для отправки запроса в Redis.Конечно, вы должны убедиться, что ваш код поточно-ориентирован, проверьте первую оптимизацию.

Уменьшите количество записей

Из вашего примера в ваших записях много дублирующихся MD5 и разные идентификаторы,Так много запросов к Redis не разрешено, так как они будут перезаписаны последующими запросами.Таким образом, вы можете выполнить (внешнюю) сортировку и удалить эти дубликаты перед отправкой запросов в Redis.

0 голосов
/ 17 июня 2019

Вам необходимо использовать команду --pipe

Сначала вы создаете файл со всеми данными в нем в следующем формате и сохраняете его как data.txt

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

После этого вы можете запустить команду --pipe

cat data.txt | redis-cli --pipe

Для подробной информации Redis Mass In Диссертация

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...