GitHubじゃ!Pythonじゃ!

GitHubからPython関係の優良リポジトリを探したかったのじゃー、でも英語は出来ないから日本語で読むのじゃー、英語社会世知辛いのじゃー

andymccurdy

redis-py – Redis Pythonクライアント

投稿日:

Redis Pythonクライアント

赤ちゃん

RedisのKey-ValueストアへのPythonインターフェイス。

インストール

redis-pyには実行中のRedisサーバーが必要です。 インストール手順については、 Redisのクイックスタートを参照してください。

redis-pyをインストールするには、次のようにします。

$ sudo pip install redis

または代わりに(あなたは本当にピップを使用する必要があります):

$ sudo easy_install redis

またはソースから:

$ sudo python setup.py install

入門

>>> import redis
>>> r = redis.StrictRedis(host='localhost', port=6379, db=0)
>>> r.set('foo', 'bar')
True
>>> r.get('foo')
'bar'

デフォルトでは、すべての応答はPython 3ではバイトとして、Python 2ではstrとして返されます。ユーザーはPython 3文字列またはPython 2ユニコードオブジェクトをデコードする責任があります。

クライアントからのすべての文字列応答をデコードする必要がある場合、ユーザーはdecode_responses = TrueをStrictRedis .__ init__に指定できます。 この場合、文字列型を返すRedisコマンドは、指定されたエンコーディングでデコードされます。

APIリファレンス

公式のRedisコマンドのドキュメントは、各コマンドについて詳しく説明しています。 redis-pyは、これらのコマンドを実装する2つのクライアントクラスを公開します。 StrictRedisクラスは、公式のコマンド構文を遵守しようとします。 例外はいくつかあります。

  • SELECT :実装されていません。 以下のスレッドセーフセクションの説明を参照してください。
  • DEL : ‘del’はPython構文の予約語です。 したがって、redis-pyは代わりに「削除」を使用します。
  • CONFIG GET | SET :これは、config_getまたはconfig_setとして別々に実装されます。
  • MULTI / EXEC :これらはPipelineクラスの一部として実装されています。 パイプラインは、実行時にMULTIおよびEXECステートメントでラップされます。これは、transaction = Falseを指定することによって無効にすることができます。 以下のパイプラインについての詳細を参照してください。
  • SUBSCRIBE / LISTEN :PubSubはパイプラインと同様に、非pubsubコマンドを実行できない状態で基本接続を配置するため、別のクラスとして実装されています。 Redisクライアントからpubsubメソッドを呼び出すと、PubSubのインスタンスが返されます。このインスタンスでは、チャンネルを購読してメッセージを聞くことができます。 RedisクライアントからのみPUBLISHを呼び出すことができます(詳細はissue#151のこのコメントを参照してください)。
  • SCAN / SSCAN / HSCAN / ZSCAN :* SCANコマンドは、Redisのマニュアルにあるように実装されています。 さらに、各コマンドには、等価イテレータメソッドがあります。 これらは、便宜上のものであり、ユーザーは反復中にカーソルを追跡する必要はありません。 この動作には、scan_iter / sscan_iter / hscan_iter / zscan_iterメソッドを使用します。

上記の変更に加えて、StrictRedisのサブクラスであるRedisクラスは、古いバージョンのredis-pyとの下位互換性を提供するいくつかの他のコマンドをオーバーライドします。

  • LREM : ‘num’と ‘value’引数の順序が逆転し、 ‘num’はデフォルト値のゼロになります。
  • ZADD :Redisは ‘value’の前に ‘score’引数を指定します。 これらは実装されているときに誤ってスワップされ、人々がすでにそれを使用してしまうまで発見されませんでした。 Redisクラスは* argsをname1、score1、name2、score2、…の形式で想定しています
  • SETEX : ‘時間’と ‘値’の引数の順序が逆転しました。

もっと詳しく

接続プール

背後では、redis-pyは接続プールを使用してRedisサーバーへの接続を管理します。 デフォルトでは、作成した各Redisインスタンスは、独自の接続プールを作成します。 この動作を無効にして、すでに作成された接続プールインスタンスをRedisクラスのconnection_pool引数に渡すことで、既存の接続プールを使用できます。 クライアントサイドシャーディングを実装したり、接続の管理方法を細かく制御したりするために、これを選択することができます。

>>> pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
>>> r = redis.Redis(connection_pool=pool)

接続

ConnectionPoolsは一連のConnectionインスタンスを管理します。 redis-pyには、2種類の接続があります。 デフォルトのConnectionは、通常のTCPソケットベースの接続です。 UnixDomainSocketConnectionは、サーバと同じデバイス上で実行されているクライアントがUnixドメインソケット経由で接続できるようにします。 UnixDomainSocketConnection接続を使用するには、Unixドメインソケットファイルに文字列であるunix_socket_path引数を渡します。 さらに、unixsocketパラメータがredis.confファイルで定義されていることを確認してください。 これはデフォルトでコメントアウトされています。

>>> r = redis.Redis(unix_socket_path='/tmp/redis.sock')

独自のConnectionサブクラスを作成することもできます。 これは、非同期フレームワーク内でソケット動作を制御したい場合に便利です。 独自の接続を使用してクライアントクラスをインスタンス化するには、クラスをconnection_class引数に渡して接続プールを作成する必要があります。 プールに渡す他のキーワードパラメータは、初期化中に指定されたクラスに渡されます。

>>> pool = redis.ConnectionPool(connection_class=YourConnectionClass,
                                your_arg='...', ...)

パーサー

パーサークラスは、Redisサーバーからの応答がどのように解析されるかを制御する方法を提供します。 redis-pyには、PythonParserとHiredisParserの2つのパーサクラスが付属しています。 デフォルトでは、redis-pyは、hiredisモジュールがインストールされていて、それ以外の場合はPythonParserにフォールバックする場合、HiredisParserを使用しようとします。

HiredisはRedisのコアチームが管理するCライブラリです。 Pieter Noordhuisは、Pythonバインディングを作成するのに十分親切でした。 Hiredisを使用すると、Redisサーバーからの応答を解析する際に最大10倍の速度向上を実現できます。 パフォーマンスの向上は、LRANGEまたはSMEMBERS操作など、多くのデータを取得する場合に最も顕著になります。

HiredisはPyPI上で利用可能で、redis-pyのようにpipやeasy_installでインストールすることができます。

$ pip install hiredis

または

$ easy_install hiredis

応答コールバック

クライアントクラスは、一連のコールバックを使用して適切なPython型へのRedis応答をキャストします。 これらのコールバックは、RESPONSE_CALLBACKSという辞書のRedisクライアントクラスで定義されています。

カスタムコールバックは、set_response_callbackメソッドを使用して、インスタンスごとに追加できます。 このメソッドは、コマンド名とコールバックの2つの引数を受け取ります。 この方法で追加されるコールバックは、コールバックが追加されるインスタンスでのみ有効です。 コールバックをグローバルに定義またはオーバーライドする場合は、Redisクライアントのサブクラスを作成し、コールバックをRESPONSE_CALLBACKSクラスのディクショナリに追加する必要があります。

応答コールバックには、少なくとも1つのパラメータ、つまりRedisサーバーからの応答が必要です。 また、応答を解釈する方法をさらに制御するために、キーワード引数を受け入れることもできます。 これらのキーワード引数は、コマンドがexecute_commandを呼び出す際に指定します。 ZRANGE実装では、応答コールバックキーワード引数に “withscores”引数を使用する方法を示します。

スレッドセーフティ

Redisクライアントインスタンスはスレッド間で安全に共有できます。 内部的には、接続インスタンスはコマンド実行中に接続プールから取得され、その後すぐにプールに戻されます。 コマンドの実行は、クライアントインスタンスの状態を決して変更しません。

しかし、1つの注意点があります:Redis SELECTコマンドです。 SELECTコマンドを使用すると、接続によって現在使用中のデータベースを切り替えることができます。 そのデータベースは、別のデータベースが選択されるまで、または接続が閉じられるまで選択されたままです。 これにより、異なるデータベースに接続されているプールに接続が返されるという問題が発生します。

その結果、redis-pyはクライアントインスタンスでSELECTコマンドを実装しません。 同じアプリケーション内で複数のRedisデータベースを使用する場合は、データベースごとに個別のクライアントインスタンス(場合によっては別々の接続プール)を作成する必要があります。

PubSubまたはPipelineオブジェクトをスレッド間で渡すことは安全ではありません。

パイプライン

パイプラインは、単一の要求で複数のコマンドをサーバーにバッファリングするためのサポートを提供する、基本Redisクラスのサブクラスです。 クライアントとサーバー間の前後のTCPパケット数を減らすことで、コマンドグループのパフォーマンスを大幅に向上させることができます。

パイプラインは使い方が簡単です:

>>> r = redis.Redis(...)
>>> r.set('bing', 'baz')
>>> # Use the pipeline() method to create a pipeline instance
>>> pipe = r.pipeline()
>>> # The following SET commands are buffered
>>> pipe.set('foo', 'bar')
>>> pipe.get('bing')
>>> # the EXECUTE call sends all buffered commands to the server, returning
>>> # a list of responses, one for each command.
>>> pipe.execute()
[True, 'baz']

使い易さのために、パイプラインにバッファリングされているすべてのコマンドは、パイプラインオブジェクト自体を返します。 したがって、呼び出しは次のように連鎖できます。

>>> pipe.set('foo', 'bar').sadd('faz', 'baz').incr('auto_number').execute()
[True, True, 6]

さらに、パイプラインは、バッファされたコマンドがグループとして原子的に実行されるようにすることもできます。 これはデフォルトで発生します。 パイプラインのアトミックな性質を無効にしたいが、依然としてコマンドをバッファしたい場合は、トランザクションをオフにすることができます。

>>> pipe = r.pipeline(transaction=False)

一般的な問題は、アトミックトランザクションを必要とするが、トランザクション内で使用する前にRedisで値を取得する必要がある場合に発生します。 たとえば、INCRコマンドが存在しないと仮定し、PythonでINCRのアトミックバージョンを構築する必要があるとします。

完全に素朴な実装では、値を取得し、Pythonでインクリメントし、新しい値を戻すことができます。 しかし、これはアトミックではありません。なぜなら、同時に複数のクライアントがGETから同じ値を取得するためです。

WATCHコマンドを入力します。 ウォッチは、トランザクションを開始する前に1つまたは複数のキーを監視する機能を提供します。 これらのキーのいずれかがそのトランザクションの実行前に変更されると、トランザクション全体がキャンセルされ、WatchErrorが発生します。 独自のクライアントサイドINCRコマンドを実装するには、次のようにします。

>>> with r.pipeline() as pipe:
...     while 1:
...         try:
...             # put a WATCH on the key that holds our sequence value
...             pipe.watch('OUR-SEQUENCE-KEY')
...             # after WATCHing, the pipeline is put into immediate execution
...             # mode until we tell it to start buffering commands again.
...             # this allows us to get the current value of our sequence
...             current_value = pipe.get('OUR-SEQUENCE-KEY')
...             next_value = int(current_value) + 1
...             # now we can put the pipeline back into buffered mode with MULTI
...             pipe.multi()
...             pipe.set('OUR-SEQUENCE-KEY', next_value)
...             # and finally, execute the pipeline (the set command)
...             pipe.execute()
...             # if a WatchError wasn't raised during execution, everything
...             # we just did happened atomically.
...             break
...        except WatchError:
...             # another client must have changed 'OUR-SEQUENCE-KEY' between
...             # the time we started WATCHing it and the pipeline's execution.
...             # our best bet is to just retry.
...             continue

PipelineはWATCHの間、単一の接続にバインドする必要があるため、reset()メソッドを呼び出すことによって接続が接続プールに確実に戻されるように注意する必要があります。 上記の例のように、パイプラインをコンテキストマネージャとして使用すると、reset()が自動的に呼び出されます。 もちろん、reset()を明示的に呼び出すことで手動で行うこともできます:

>>> pipe = r.pipeline()
>>> while 1:
...     try:
...         pipe.watch('OUR-SEQUENCE-KEY')
...         ...
...         pipe.execute()
...         break
...     except WatchError:
...         continue
...     finally:
...         pipe.reset()

ウォッチ・エラーの処理と再試行の定型文をすべて処理するための “transaction”という便利なメソッドがあります。 単一のパラメータ、パイプラインオブジェクト、および任意の数のキーがWATCHされることを期待する呼び出し可能関数が必要です。 上記のクライアントサイドのINCRコマンドは次のように書くことができます。これは読みやすくなります。

>>> def client_side_incr(pipe):
...     current_value = pipe.get('OUR-SEQUENCE-KEY')
...     next_value = int(current_value) + 1
...     pipe.multi()
...     pipe.set('OUR-SEQUENCE-KEY', next_value)
>>>
>>> r.transaction(client_side_incr, 'OUR-SEQUENCE-KEY')
[True]

パブリッシュ/サブスクライブ

redis-pyには、チャンネルを購読して新しいメッセージを聞くPubSubオブジェクトが含まれています。 PubSubオブジェクトの作成は簡単です。

>>> r = redis.StrictRedis(...)
>>> p = r.pubsub()

PubSubインスタンスが作成されると、チャネルとパターンをサブスクライブすることができます。

>>> p.subscribe('my-first-channel', 'my-second-channel', ...)
>>> p.psubscribe('my-*', ...)

PubSubインスタンスは、これらのチャネル/パターンにサブスクライブされています。 サブスクリプションの確認は、PubSubインスタンスからメッセージを読み取ることで確認できます。

>>> p.get_message()
{'pattern': None, 'type': 'subscribe', 'channel': 'my-second-channel', 'data': 1L}
>>> p.get_message()
{'pattern': None, 'type': 'subscribe', 'channel': 'my-first-channel', 'data': 2L}
>>> p.get_message()
{'pattern': None, 'type': 'psubscribe', 'channel': 'my-*', 'data': 3L}

PubSubのインスタンスから読み取られるすべてのメッセージは、以下のキーを持つ辞書になります。

  • 「subscribe」、「unsubscribe」、「psubscribe」、「punsubscribe」、「message」、「pmessage」のいずれかを入力します。
  • channel :チャンネル[un]が購読されているチャンネルまたはメッセージが公開されたチャンネル
  • パターン :公開されたメッセージのチャンネルと一致するパターン。 ‘pmessage’型を除くすべての場合に、Noneになります。
  • data :メッセージデータ。 [un] subscribeメッセージの場合、この値は接続が現在サブスクライブされているチャネルとパターンの数になります。 [p]メッセージメッセージでは、この値は実際に公開されたメッセージになります。

今すぐメッセージを送りましょう。

# the publish method returns the number matching channel and pattern
# subscriptions. 'my-first-channel' matches both the 'my-first-channel'
# subscription and the 'my-*' pattern subscription, so this message will
# be delivered to 2 channels/patterns
>>> r.publish('my-first-channel', 'some data')
2
>>> p.get_message()
{'channel': 'my-first-channel', 'data': 'some data', 'pattern': None, 'type': 'message'}
>>> p.get_message()
{'channel': 'my-first-channel', 'data': 'some data', 'pattern': 'my-*', 'type': 'pmessage'}

サブスクライブ解除は、サブスクライブと同じように機能します。 引数が[p] unsubscribeに渡されない場合、すべてのチャンネルまたはパターンは登録解除されます。

>>> p.unsubscribe()
>>> p.punsubscribe('my-*')
>>> p.get_message()
{'channel': 'my-second-channel', 'data': 2L, 'pattern': None, 'type': 'unsubscribe'}
>>> p.get_message()
{'channel': 'my-first-channel', 'data': 1L, 'pattern': None, 'type': 'unsubscribe'}
>>> p.get_message()
{'channel': 'my-*', 'data': 0L, 'pattern': None, 'type': 'punsubscribe'}

redis-pyでは、公開されたメッセージを処理するコールバック関数を登録することもできます。 メッセージハンドラは単一の引数をとります。これは上記の例のような辞書です。 メッセージハンドラを使用してチャネルまたはパターンをサブスクライブするには、チャネルまたはパターン名をキーワード引数として渡し、その値をコールバック関数にします。

メッセージがメッセージハンドラでチャネルまたはパターンで読み取られると、メッセージ辞書が作成されてメッセージハンドラに渡されます。 この場合、メッセージはすでに処理されているため、get_message()からNone値が返されます。

>>> def my_handler(message):
...     print 'MY HANDLER: ', message['data']
>>> p.subscribe(**{'my-channel': my_handler})
# read the subscribe confirmation message
>>> p.get_message()
{'pattern': None, 'type': 'subscribe', 'channel': 'my-channel', 'data': 1L}
>>> r.publish('my-channel', 'awesome data')
1
# for the message handler to work, we need tell the instance to read data.
# this can be done in several ways (read more below). we'll just use
# the familiar get_message() function for now
>>> message = p.get_message()
MY HANDLER:  awesome data
# note here that the my_handler callback printed the string above.
# `message` is None because the message was handled by our handler.
>>> print message
None

あなたのアプリケーションが(時々雑音の多い)購読/購読中止の確認メッセージに興味がない場合は、ignore_subscribe_messages = Trueをr.pubsub()に渡して無視することができます。 これにより、すべての購読/購読解除メッセージが読み取られますが、アプリケーションにバブルアップすることはありません。

>>> p = r.pubsub(ignore_subscribe_messages=True)
>>> p.subscribe('my-channel')
>>> p.get_message()  # hides the subscribe message and returns None
>>> r.publish('my-channel')
1
>>> p.get_message()
{'channel': 'my-channel', 'data': 'my data', 'pattern': None, 'type': 'message'}

メッセージを読むための3つの戦略があります。

上記の例では、pubsub.get_message()を使用しています。 背後では、get_message()はシステムの ‘select’モジュールを使用して接続のソケットをすばやくポーリングします。 読み込み可能なデータがある場合、get_message()はそれを読み込み、メッセージをフォーマットして返すか、メッセージハンドラに渡します。 読み込むデータがない場合、get_message()はただちにNoneを返します。 これにより、アプリケーション内の既存のイベントループに統合するのが簡単になります。

>>> while True:
>>>     message = p.get_message()
>>>     if message:
>>>         # do something with the message
>>>     time.sleep(0.001)  # be nice to the system :)

古いバージョンのredis-pyは、pubsub.listen()でメッセージを読み取るだけです。 listen()は、メッセージが利用可能になるまでブロックするジェネレータです。 アプリケーションがredisから受信したメッセージを受信して​​処理する必要がない場合、listen()は簡単に実行を開始する方法です。

>>> for message in p.listen():
...     # do something with the message

3番目のオプションは別のスレッドでイベントループを実行します。 pubsub.run_in_thread()は新しいスレッドを作成し、イベントループを開始します。 スレッドオブジェクトはrun_in_thread()の呼び出し側に返されます。 呼び出し元は、thread.stop()メソッドを使用してイベントループとスレッドをシャットダウンできます。 背後では、これは別のスレッドで実行されるget_message()のラッパーです。本質的に小さな非ブロッキングイベントループを作成します。 run_in_thread()はオプションのsleep_time引数をとります。 指定された場合、イベントループは、ループの各繰り返しで値を指定してtime.sleep()を呼び出します。

注意:別のスレッドで実行しているので、登録されたメッセージハンドラでは自動的に処理されないメッセージは処理できません。 したがって、メッセージハンドラが添付されていないパターンやチャンネルを購読している場合、redis-pyはrun_in_thread()を呼び出さないようにします。

>>> p.subscribe(**{'my-channel': my_handler})
>>> thread = p.run_in_thread(sleep_time=0.001)
# the event loop is now running in the background processing messages
# when it's time to shut it down...
>>> thread.stop()

PubSubオブジェクトは、作成されたクライアントインスタンスと同じエンコーディングセマンティクスに準拠しています。 ユニコードのチャンネルまたはパターンは、クライアントで指定された文字セットを使用してエンコードされてから、Redisに送信されます。 クライアントのdecode_responsesフラグがFalse(デフォルト)に設定されている場合、メッセージ辞書の ‘channel’、 ‘pattern’、 ‘data’の値はバイト文字列(Python 2ではstr、Python 3ではバイト)になります。 クライアントのdecode_responsesがTrueの場合、 ‘channel’、 ‘pattern’および ‘data’の値は、クライアントの文字セットを使用してUnicode文字列に自動的にデコードされます。

PubSubオブジェクトは、それらが購読されているチャネルとパターンを覚えています。 ネットワークエラーやタイムアウトなどの切断が発生した場合、PubSubオブジェクトは再接続時に以前のすべてのチャネルとパターンに再登録されます。 クライアントが切断されている間に発行されたメッセージは配信できません。 PubSubオブジェクトが終了したら、.close()メソッドを呼び出して接続をシャットダウンします。

>>> p = r.pubsub()
>>> ...
>>> p.close()

サブコマンドCHANNELS、NUMSUBおよびNUMPATのPUBSUBセットもサポートされています。

>>> r.pubsub_channels()
['foo', 'bar']
>>> r.pubsub_numsub('foo', 'bar')
[('foo', 9001), ('bar', 42)]
>>> r.pubsub_numsub('baz')
[('baz', 0)]
>>> r.pubsub_numpat()
1204

LUAスクリプティング

redis-pyは、EVAL、EVALSHA、およびSCRIPTコマンドをサポートしています。 しかし、これらのコマンドを現実のシナリオで使用することを退屈にする多くのエッジケースがあります。 したがって、redis-pyはScriptオブジェクトを公開しているため、スクリプティングははるかに使いやすくなります。

スクリプトインスタンスを作成するには、最初の引数としてLUAコードを渡すクライアントインスタンスでregister_script関数を使用します。 register_scriptは、コード全体で使用できるスクリプトインスタンスを返します。

以下の簡単なLUAスクリプトは、キーの名前と乗数の2つのパラメータを受け入れます。 スクリプトは、キーに格納されている値を取り出し、それを乗数値と乗算して結果を返します。

>>> r = redis.StrictRedis()
>>> lua = """
... local value = redis.call('GET', KEYS[1])
... value = tonumber(value)
... return value * ARGV[1]"""
>>> multiply = r.register_script(lua)

multiplyは、関数のように呼び出すことによって呼び出されるScriptインスタンスになりました。 スクリプトインスタンスは、次のオプションの引数を受け入れます。

  • keys :スクリプトがアクセスするキー名のリスト。 これはLUAのKEYSリストになります。
  • args :引数の値のリスト。 これはLUAのARGVリストになります。
  • client :スクリプトを呼び出すredis-py ClientまたはPipelineインスタンス。 clientが指定されていない場合、Scriptインスタンスを最初に作成したクライアント(register_scriptが呼び出されたクライアント)が使用されます。

上の例を続ける:

>>> r.set('foo', 2)
>>> multiply(keys=['foo'], args=[5])
10

キー ‘foo’の値は2に設定されています。乗算が呼び出されると、 ‘foo’キーが乗数5とともにスクリプトに渡されます。LUAはスクリプトを実行し、結果10を返します。

スクリプトインスタンスは、完全に異なるRedisサーバーを指し示すものであっても、異なるクライアントインスタンスを使用して実行できます。

>>> r2 = redis.StrictRedis('redis2.example.com')
>>> r2.set('foo', 3)
>>> multiply(keys=['foo'], args=[5], client=r2)
15

Scriptオブジェクトは、LUAスクリプトがRedisのスクリプトキャッシュにロードされることを保証します。 NOSCRIPTエラーが発生した場合、スクリプトをロードして実行を再試行します。

スクリプトオブジェクトは、パイプラインでも使用できます。 スクリプトを呼び出すときには、パイプラインインスタンスをクライアント引数として渡す必要があります。 パイプライン実行の直前にスクリプトがRedisのスクリプトキャッシュに確実に登録されるように注意してください。

>>> pipe = r.pipeline()
>>> pipe.set('foo', 5)
>>> multiply(keys=['foo'], args=[5], client=pipe)
>>> pipe.execute()
[True, 25]

センチネルのサポート

redis-pyをRedis Sentinelとともに使用すると、Redisノードを検出できます。 redis-pyのSentinelサポートを使用するには、少なくとも1つのSentinelデーモンを実行する必要があります。

redis-pyをSentinelインスタンスに接続するのは簡単です。 Sentinel接続を使用して、マスタとスレーブのネットワークアドレスを検出できます。

>>> from redis.sentinel import Sentinel
>>> sentinel = Sentinel([('localhost', 26379)], socket_timeout=0.1)
>>> sentinel.discover_master('mymaster')
('127.0.0.1', 6379)
>>> sentinel.discover_slaves('mymaster')
[('127.0.0.1', 6380)]

SentinelインスタンスからRedisクライアント接続を作成することもできます。 マスター(書き込み操作の場合)またはスレーブ(読み取り専用操作の場合)のいずれかに接続できます。

>>> master = sentinel.master_for('mymaster', socket_timeout=0.1)
>>> slave = sentinel.slave_for('mymaster', socket_timeout=0.1)
>>> master.set('foo', 'bar')
>>> slave.get('foo')
'bar'

マスターオブジェクトとスレーブオブジェクトは、接続プールがSentinelインスタンスにバインドされた通常のStrictRedisインスタンスです。 Sentinelをサポートするクライアントは、接続を確立しようとすると、最初にSentinelサーバーに問い合わせて、接続する適切なホストを決定します。 サーバーが見つからない場合は、MasterNotFoundErrorまたはSlaveNotFoundErrorが発生します。 どちらの例外もConnectionErrorのサブクラスです。

スレーブクライアントに接続しようとすると、接続可能なスレーブが見つかるまで、Sentinel接続プールはスレーブのリストを反復処理します。 スレーブが接続できない場合、マスターとの接続が確立されます。

Redis Sentinelの詳細については、Redis Sentinelのサポートに関するRedisクライアントのガイドラインを参照してください。

イテレータをスキャンする

Redis 2.8で導入された* SCANコマンドは、使用するのが面倒です。 これらのコマンドは完全にサポートされていますが、redis-pyは、便宜上、Pythonイテレータを返す以下のメソッドscan_iter、hscan_iter、sscan_iter、zscan_iterも公開しています。

>>> for key, value in (('A', '1'), ('B', '2'), ('C', '3')):
...     r.set(key, value)
>>> for key in r.scan_iter():
...     print key, r.get(key)
A 1
B 2
C 3

著者

redis-pyはAndy McCurdy( sedrik@gmail.com )によって開発され、維持されています。 それはここに見つけることができます: http : //github.com/andymccurdy/redis-py

特別なおかげで:

  • 元のPython Redisクライアントの作者であるLudovico Magnocavalloは、そこからいくつかのソケットコードが引き続き使用されています。
  • 一般的な応答コールバックシステムに関するアイデアはAlexander Solovyovにあります。
  • 最初のパッケージングサポートはPaul Hubbardです。







-andymccurdy

執筆者: