4

memcachedb に大量のデータをロードしようとしています。MySQL データベースでいくつかのクエリを実行しています。後で簡単にアクセスできるように、これらのクエリの結果を memcachedb に保存したいと考えています。

現在、単純な set コマンドを使用して結果を memcachedb に保存していましたが、これらの結果は数十億あるため、1 つずつループに保存するのは非常に非効率的で時間がかかります。それで、データを memcachedb にロードするためのより良い方法があるかどうか疑問に思っていましたか? 従来の RDMS のデータ インポート ウィザードのように

pylibmc を使用して memcachedb に接続しています。

4

1 に答える 1

4

pylibmc ライブラリには、一連set_multiのコマンドを一度に送信する関数があります。

mc.set_multi({
    'key': 'Hello',
    'another': True,
    #[..]
})

これはおそらく十分に機能するはずです。何十億ものキーがある場合、おそらくそれを数千のチャンクに分割したいと思うでしょう。

ソケットを介してコマンドを送信するだけで、おそらくもう少しパフォーマンスを絞ることができます。memcache プロトコルは 非常に単純です。これには、フラグを追加できるという利点があるnoreplyため、サーバーはわざわざ返信を送信しません。もちろん、これはエラーチェックを行うことができないことを意味し、何らかの理由でいくつかのキーを失うことは問題ありません.

簡単な概念実証は次のとおりです。

#!/usr/bin/env python

import socket

data = 'set key_1 0 86400 5\r\nabcde\r\n'
data += 'set key_2 0 86400 5\r\nzxcvb\r\n'

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 11211))
s.sendall(data)
print(s.recv(8192))
s.close()

# Verify if it worked!
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 11211))
s.sendall('get key_1\r\n')
s.sendall('get key_2\r\n')
print(s.recv(8192))
s.close()

どちらが出力されますか:

STORED
STORED

VALUE key_1 0 5
abcde
END
VALUE key_2 0 5
zxcvb
END

setコマンドの形式は次のとおりです。

set <key> <flags> <exptime> <data_size> [noreply]\r\n
<data>\r\n

もちろん、これは単なる概念実証です。もう少し高度な例は次のようになります。

#!/usr/bin/env python

import socket

def make_set(n, data):
    return 'set key_{} 0 86400 {}\r\n{}\r\n'.format(n, len(data), data)

data = open('/etc/aliases').readlines()
commands = [ make_set(n, d.strip()) for n, d in enumerate(data) if d.strip() != '' ]

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 11211))
s.sendall(''.join(commands))
print(s.recv(65000))

# Verify if it worked!
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 11211))
for n in range(0, len(commands)):
    s.sendall('get key_{}\r\n'.format(n))
print(s.recv(65000))
s.close()

MySQL からデータを取得している場合はset、SQL クエリを使用してコマンドを作成することを検討してください。例えば:

select
    concat('set key_', page_id, ' 0 86400 ', length(page_title), '\r\n', page_title, '\r\n')
    as cmd
from page limit 2;

これが実際に速いかどうかはわかりませんが、速いと思います。

于 2016-03-03T22:26:04.183 に答える