簡體   English   中英

將 dataframe 發送到 Redis 的最快方式

[英]Fastest way to send dataframe to Redis

我有一個包含 2 列的 dataframe。 對於每一行,我只想創建一個 Redis 集,其中 dataframe 的第一個值是鍵,第二個值是 Redis 集的值。 我已經完成了研究,我想我找到了通過迭代最快的方法:

def send_to_redis(df, r):
    df['bin_subscriber'] = df.apply(lambda row: uuid.UUID(row.subscriber).bytes, axis=1)
    df['bin_total_score'] = df.apply(lambda row: struct.pack('B', round(row.total_score)), axis=1)
    df = df[['bin_subscriber', 'bin_total_score']]
    with r.pipeline() as pipe:
        index = 0
        for subscriber, total_score in zip(df['bin_subscriber'], df['bin_total_score']):
            r.set(subscriber, total_score)
            if (index + 1) % 2000 == 0:
                pipe.execute()
            index += 1

有了這個,我可以每分鍾向 Redis 發送大約 400-500k 套。 我們最終可能會處理多達 3 億個,按照這個速度,這需要半天左右的時間。 可行但不理想。 請注意,在外包裝中,我一次從 s3 下載 .parquet 文件,並通過 IO 字節拉入 Pandas 。

def process_file(s3_resource, r, bucket, key):
    buffer = io.BytesIO()
    s3_object = s3_resource.Object(bucket, key)
    s3_object.download_fileobj(buffer)
    send_to_redis(
        pandas.read_parquet(buffer, columns=['subscriber', 'total_score']), r)

def main():
    args = get_args()
    s3_resource = boto3.resource('s3')
    r = redis.Redis()
    file_prefix = get_prefix(args)
    s3_keys = [
        item.key for item in
        s3_resource.Bucket(args.bucket).objects.filter(Prefix=file_prefix)
        if item.key.endswith('.parquet')
    ]
    for key in s3_keys:
        process_file(s3_resource, r, args.bucket, key)



有沒有辦法在不使用迭代的情況下將此數據發送到 Redis? 是否可以將整個數據塊發送到 Redis 並讓 Redis 為數據塊的每個第一個和第二個值設置鍵和值? 我想那會稍微快一點。

我拉入 Pandas 的原始鑲木地板是通過 Pyspark 創建的。 我嘗試使用速度非常快的 Spark-Redis 插件,但我不確定如何在 Spark dataframe 本身中將我的數據轉換為上述二進制文件,而且我不喜歡如何將列名添加為字符串到每一個值,它似乎不是可配置的。 每個具有 label 的 redis object 似乎空間效率都很低。

任何建議將不勝感激!

使用 --pipe 嘗試Redis Mass Insertionredis 批量導入

  1. 創建一個包含 Redis 命令的新文本文件input.txt
Set Key0 Value0
set Key1 Value1
...
SET Keyn Valuen
  1. 使用redis-mass.py (見下文)插入 redis
python redis-mass.py input.txt | redis-cli --pipe

來自github的 redis-mass.py。

#!/usr/bin/env python
"""
    redis-mass.py
    ~~~~~~~~~~~~~
    Prepares a newline-separated file of Redis commands for mass insertion.
    :copyright: (c) 2015 by Tim Simmons.
    :license: BSD, see LICENSE for more details.
"""
import sys

def proto(line):
    result = "*%s\r\n$%s\r\n%s\r\n" % (str(len(line)), str(len(line[0])), line[0])
    for arg in line[1:]:
        result += "$%s\r\n%s\r\n" % (str(len(arg)), arg)
    return result

if __name__ == "__main__":
    try:
        filename = sys.argv[1]
        f = open(filename, 'r')
    except IndexError:
        f = sys.stdin.readlines()

    for line in f:
        print(proto(line.rstrip().split(' ')),)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM