Как преобразовать большой поток в сжатую строку base64

1

Я создаю платформу аналитики, и я хочу сжать мои задания ETL (Extract Transform Load), прежде чем хранить их в своей базе данных. Прежде чем я начну писать код, мне было интересно, может ли кто-то с некоторым опытом рассказать мне, как это сделать должным образом. Я хочу gzip данные, а затем преобразовать его в строку base64. Я просто gzip и конвертирую в base64 или это не сработает?

Это тот процесс, который я сейчас использую для этих больших наборов данных.

var streamObj = athenaClient.execute('my query').toStream()
var data = [];

redis.set('Some Dashboard Data', '[')

streamObj.on('data', function(record) {
    // TODO gzip record then convert to base64
    if (data.length === 500) {
        let tempData = JSON.stringify(data);
        data = []
        redis.append('Some Dashboard Data', tempData.slice(1, tempData.length - 1) + ',')
        }
        data.push(record);
    })
}

Если это невозможно, можно ли вместо этого сохранить gzip-строку?

  • 1
    почему data.length === 500? Это то, как вы разделяете поток?
  • 0
    Узлу не хватает памяти, если я не сделаю это таким образом и вызывает переполнение стека;)
Показать ещё 3 комментария
Теги:
node-redis
amazon-athena
zlib

2 ответа

1
Лучший ответ

Просто чтобы уточнить ответ Зильвинаса. Я покажу вам все, как я заработал.

const athena = require('./athena')
const redis = require('./redis')
const zlib = require('zlib')
const Stream = require('stream')

exports.persistStream = (config, query, name, transform) => {
return new Promise((resolve, reject) => {
    let recordCount = 0

    var transformStream = new Stream.Transform({ writableObjectMode: true, readableObjectMode: true})
    transformStream._transform = function (chunk, encoding, done) {

        recordCount++

        if (transform) chunk = transform(chunk)

        let jsonChunk = JSON.stringify([chunk])

        switch (true) {
            case recordCount === 1: 
                jsonChunk = jsonChunk.slice(0, jsonChunk.length - 1); break
            default:
                jsonChunk = ',' + jsonChunk.slice(1, jsonChunk.length - 1); break
        }
        this.push(jsonChunk)
        done();
    };

    transformStream._final = function (done) {
        this.push(']')
        done()
    }

    const gzip = zlib.createGzip()

    let buffers = []

    var stream = athena.execute(query)
        .toStream()
        .pipe(transformStream)
        .pipe(gzip)

    gzip.on('data', (chunk) => {
        buffers.push(chunk)
    })

    gzip.on('end', function () {
        let buffer = Buffer.concat(buffers)
        redis.set(name, buffer.toString('base64'), (err, response) => {
            zlib.gzip(config, (err, buff) => {
                redis.set(name + ' Config', buff.toString('base64'), (err, response) => {
                    if (err) {
                        console.log(err)
                        reject()
                    } else {

                        console.log(name + ' succeeded')
                        resolve()
                    }
                })
            })
        })
    })

    stream.on('error', (err) => {
        console.log(err)
        reject()
    })
})
}
  • 0
    Надеюсь, это поможет кому-то!
1

Пусть среда управления окружением node.js использует обратное давление, обеспечиваемое потоками.

Я бы рассмотрел это решение:

inputStream
    .pipe(zlib)
    .pipe(transformToBase64Stream)
    .pipe(redisCli);

zlib является родным, поэтому это не должно вызывать никаких проблем. Чтобы преобразовать в base64, вы можете написать поток преобразования или использовать внешние инструменты. Чтобы транслировать результаты в redis потоком, вы можете запустить дочерний процесс redis-cli в режиме pipe. Как упоминалось в статьях массовой вставки и redis cli, для больших данных предлагается, но вы должны сами обрабатывать протокол redis. Прочтите предоставленные статьи и сообщите мне, помогли ли они решить вашу проблему.

  • 0
    Спасибо за это понимание. Я попытаюсь применить это в контексте реальной жизни, а затем дам вам знать, как это происходит.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню