>  기사  >  백엔드 개발  >  Redis용 비복제 샤딩을 구현하는 Python 라이브러리인 Rb(redis blaster)

Redis용 비복제 샤딩을 구현하는 Python 라이브러리인 Rb(redis blaster)

WBOY
WBOY앞으로
2023-04-11 19:27:271643검색

Rb, redis blaster는 redis용 비복제 샤딩을 구현하는 라이브러리입니다. Python Redis 위에 사용자 정의 라우팅 시스템을 구현하여 요청을 개별 노드에 수동으로 라우팅할 필요 없이 자동으로 다른 서버를 대상으로 지정할 수 있습니다.

redis의 모든 기능을 구현하지도 않고 그렇게 하려고 시도하지도 않습니다. 클라이언트를 항상 특정 호스트에 연결할 수 있지만 대부분의 작업은 자동으로 다른 노드로 라우팅될 수 있는 기본 키/값 작업으로 제한되어 있다고 가정합니다.

할 수 있는 작업:

  • 호스트에서 단일 키 작업을 자동으로 수행합니다.
  • 전체 또는 일부 노드에서 명령을 실행합니다.
  • 이 모든 것을 병렬로 실행하세요.

Installation

rb는 PyPI에서 사용할 수 있으며 PyPI에서 설치할 수 있습니다:

$ pip install rb

Configuration

rb를 시작하는 것은 매우 쉽습니다. 이전에 py-redis를 사용해 본 적이 있다면 편안함을 느낄 것입니다. 주요 차이점은 단일 호스트에 연결하는 대신 클러스터가 여러 호스트에 연결하도록 구성된다는 것입니다.

rom rb import Cluster

cluster = Cluster(hosts={
0: {'port': 6379},
1: {'port': 6380},
2: {'port': 6381},
3: {'port': 6382},
4: {'port': 6379},
5: {'port': 6380},
6: {'port': 6381},
7: {'port': 6382},
}, host_defaults={
'host': '127.0.0.1',
})

이 경우 동일한 호스트의 4개의 서로 다른 서버 프로세스에 8개의 노드가 설정되어 있습니다. 호스트 매개변수는 연결할 호스트의 맵입니다. 사전의 키는 호스트 ID(정수)이고 값은 매개변수 사전입니다. Host_defaults는 모든 호스트에 대해 채워진 선택적 기본값의 사전입니다. 반복되는 일부 공통 기본값을 공유하려는 경우에 유용합니다(이 경우 모든 호스트가 localhost에 연결됨).

기본 구성에서는 PartitionRouter가 라우팅에 사용됩니다.

Routing

이제 클러스터가 구축되었으므로 Cluster.get_routing_client()를 사용하여 각 명령을 올바른 Redis 노드로 자동 라우팅하는 Redis 클라이언트를 얻을 수 있습니다.

client = cluster.get_routing_client()
results = {}
for key in keys_to_look_up:
results[key] = client.get(key)

클라이언트는 표준 pyredis StrictClient와 동일하게 작동합니다. 매우 유사하지만 주요 차이점은 하나의 키만 포함하는 명령만 실행할 수 있다는 것입니다.

그러나 이 기본 작업은 직렬로 실행됩니다. rb가 유용한 이유는 Redis 파이프라인을 자동으로 구축하고 여러 호스트에 쿼리를 병렬로 보낼 수 있다는 것입니다. 그러나 이제 값을 즉시 사용할 수 없기 때문에 사용법이 약간 변경됩니다.

results = {}
with cluster.map() as client:
for key in keys_to_look_up:
results[key] = client.get(key)

지금까지는 비슷해 보이지만 결과 사전에 실제 값을 저장하는 대신 Promise 개체가 저장됩니다. 맵 컨텍스트 관리자가 종료되면 실행이 보장되며 Promise.value 속성에 액세스하여 값을 얻을 수 있습니다.

for key, promise in results.iteritems():
print '%s: %s' % (key, promise.value)

모든 참여 호스트에 명령을 보내려면(예: 데이터베이스 삭제) Cluster.all() 메서드를 사용할 수 있습니다.

with cluster.all() as client:
client.flushdb()

이렇게 하면 Promise 값은 호스트 ID가 키이고 결과가 값인 사전입니다. 예:

with cluster.all() as client:
results = client.info()
for host_id, info in results.iteritems():
print 'host %s is running %s' % (host_id, info['os'])

특정 호스트를 명시적으로 대상으로 지정하려면 Cluster.fanout()을 사용하여 명령을 보낼 호스트 ID 목록을 수락할 수 있습니다.

API

이것은 공개 API에 대한 완전한 참조입니다. 이 라이브러리는 Python redis 라이브러리를 확장하므로 일부 클래스에는 더 많은 기능이 있으므로 py-redis 라이브러리를 확인해야 합니다.

Cluster

class rb.Cluster(hosts, host_defaults=None, pool_cls=None, pool_options=None, router_cls=None, router_options=None)

cluster는 rb의 핵심 개체입니다. 이는 개별 노드의 연결 풀에 저장되며 애플리케이션이 실행되는 동안 중앙 위치에서 공유될 수 있습니다.

기본 라우터가 있는 4개의 Redis 인스턴스에 있는 클러스터의 기본 예:

cluster = Cluster(hosts={
0: {'port': 6379},
1: {'port': 6380},
2: {'port': 6381},
3: {'port': 6382},
}, host_defaults={
'host': '127.0.0.1',
})

hosts는 호스트 ID 번호를 구성 매개변수에 매핑하는 호스트 사전입니다. 매개변수는 add_host() 함수의 서명에 해당합니다. 이러한 매개변수의 기본값은 host_defaults에서 가져옵니다. 풀 클래스를 재정의하려면 pool_cls 및 pool_options 매개변수를 사용합니다. 라우터의 router_cls 및 router_options에도 동일하게 적용됩니다. 풀 옵션은 소켓 시간 초과 및 유사한 매개변수를 설정하는 데 유용합니다.

  • add_host(host_id=None, 호스트='localhost', 포트=6379, unix_socket_path=None, db=0, 비밀번호=None, ssl=False, ssl_options=None)

클러스터에 새 호스트를 추가합니다. 일반적으로 호스트는 생성자를 통해 추가되고 클러스터를 처음 사용한 후에는 변경하는 것이 의미가 없기 때문에 이는 단위 테스트에만 실제로 유용합니다.

  • all(timeout=None, max_concurrency=64, auto_batch=True)

모든 호스트에 팬아웃합니다. 그 외에는 fanout()과 동일합니다.

예:

with cluster.all() as client:
client.flushdb()
  • disconnect_pools()

내부 풀에 대한 모든 연결을 끊습니다.

  • execute_commands(mapping, *args, **kwargs)

Redis 클러스터의 라우팅 키와 관련된 일련의 명령을 동시에 실행하여 값이 다음 명령에 해당하는 결과 목록인 새 매핑을 반환합니다. 같은 위치. 예:

>>> cluster.execute_commands({
... 'foo': [
... ('PING',),
... ('TIME',),
... ],
... 'bar': [
... ('CLIENT', 'GETNAME'),
... ],
... })
{'bar': [<Promise None>],
 'foo': [<Promise True>, <Promise (1454446079, 418404)>]}
  • redis.client.Script의 인스턴스인 명령은 먼저 대상 노드에 존재하는지 확인한 다음 실행 전에 대상에 로드되고 다른 명령과 인터리브될 수 있습니다.
>>> from redis.client import Script
>>> TestScript = Script(None, 'return {KEYS, ARGV}')
>>> cluster.execute_commands({
... 'foo': [
... (TestScript, ('key:1', 'key:2'), range(0, 3)),
... ],
... 'bar': [
... (TestScript, ('key:3', 'key:4'), range(3, 6)),
... ],
... })
{'bar': [<Promise [['key:3', 'key:4'], ['3', '4', '5']]>],
 'foo': [<Promise [['key:1', 'key:2'], ['0', '1', '2']]>]}

내부적으로 , FanoutClient 명령을 실행하는 데 사용됩니다.

  • fanout(hosts=None, timeout=None, max_concurrency=64, auto_batch=True)

用于获取路由客户端、开始扇出操作并 join 结果的快捷上下文管理器。

在上下文管理器中,可用的客户端是 FanoutClient。示例用法:

with cluster.fanout(hosts='all') as client: client.flushdb()
get_local_client(host_id)
  • get_local_client(host_id)

返回特定主机 ID 的本地化 client。这个 client 就像一个普通的 Python redis 客户端一样工作,并立即返回结果。

  • get_local_client_for_key(key)

类似于 get_local_client_for_key() 但根据 router 所说的 key 目的地返回 client。

  • get_pool_for_host(host_id)

返回给定主机的连接池。

redis 客户端使用此连接池来确保它不必不断地重新连接。如果要使用自定义 redis 客户端,可以手动将其作为连接池传入。

  • get_router()

返回 cluster 的 router 。如果 cluster 重新配置,router 将被重新创建。通常,您不需要自己与 router 交互,因为集群的路由客户端会自动执行此操作。

这将返回 BaseRouter 的一个实例。

  • get_routing_client(auto_batch=True)

返回一个路由客户端。该客户端能够自动将请求路由到各个主机。它是线程安全的,可以类似于主机本地客户端使用,但它会拒绝执行无法直接路由到单个节点的命令。

路由客户端的默认行为是尝试将符合条件的命令批处理成批处理版本。例如,路由到同一节点的多个 GET 命令最终可以合并为一个 MGET 命令。可以通过将 auto_batch 设置为 False 来禁用此行为。这对于调试很有用,因为 MONITOR 将更准确地反映代码中发出的命令。

有关详细信息,请参阅 RoutingClient。

  • map(timeout=None, max_concurrency=64, auto_batch=True)

用于获取路由客户端、开始映射操作并 join 结果的快捷上下文管理器。max_concurrency 定义在隐式连接发生之前可以存在多少未完成的并行查询。

在上下文管理器中,可用的客户端是 MappingClient。示例用法:

results = {}
with cluster.map() as client:
for key in keys_to_fetch:
results[key] = client.get(key)
for key, promise in results.iteritems():
print '%s => %s' % (key, promise.value)
  • remove_host(host_id)

从 client 中删除 host。这仅对单元测试真正有用。

Clients

class rb.RoutingClient(cluster, auto_batch=True)

可以路由到单个目标的客户端。

有关参数,请参见 Cluster.get_routing_client()。

  • execute_command(*args, **options)

执行命令并返回解析后的响应

  • fanout(hosts=None, timeout=None, max_concurrency=64, auto_batch=None)

返回映射操作的 context manager,该操作扇出到手动指定的主机,而不是使用路由系统。例如,这可用于清空所有主机上的数据库。context manager 返回一个 FanoutClient。示例用法:

with cluster.fanout(hosts=[0, 1, 2, 3]) as client:
results = client.info()
for host_id, info in results.value.iteritems():
print '%s -> %s' % (host_id, info['is'])

返回的 promise 将所有结果累积到由 host_id 键入的字典中。

hosts 参数是一个 host_id 列表,或者是字符串 'all' ,用于将命令发送到所有主机。

fanout API 需要非常小心地使用,因为当 key 被写入不期望它们的主机时,它可能会造成很多损坏。

  • get_fanout_client(hosts, max_concurrency=64, auto_batch=None)

返回线程不安全的扇出客户端。

返回 FanoutClient 的实例。

  • get_mapping_client(max_concurrency=64, auto_batch=None)

返回一个线程不安全的映射客户端。此客户端的工作方式类似于 redis 管道并返回最终结果对象。它需要 join 才能正常工作。您应该使用自动 join 的 map() 上下文管理器,而不是直接使用它。

返回 MappingClient 的一个实例。

  • map(timeout=None, max_concurrency=64, auto_batch=None)

返回映射操作的 context manager。这会并行运行多个查询,然后最后 join 以收集所有结果。

在上下文管理器中,可用的客户端是 MappingClient。示例用法:

results = {}
with cluster.map() as client:
for key in keys_to_fetch:
results[key] = client.get(key)
for key, promise in results.iteritems():
print '%s => %s' % (key, promise.value)

class rb.MappingClient(connection_pool, max_concurrency=None, auto_batch=True)

路由客户端使用 cluster 的 router 根据执行的 redis 命令的 key 自动定位单个节点。

매개변수는 Cluster.map()을 참조하세요.

  • cancel()

미해결 요청을 모두 취소합니다.

  • execute_command(*args, **options)

명령을 실행하고 구문 분석된 응답을 반환합니다.

  • join(timeout=None)

모든 미해결 응답이 반환되거나 시간 초과될 때까지 기다립니다.

  • mget(keys , *args)

키와 동일한 순서로 값 목록을 반환합니다

  • mset(*args, **kwargs)

매핑에 따라 키/값을 설정합니다. 맵은 키/값 쌍의 사전입니다. 키와 값은 모두 문자열이거나 str()을 통해 문자열로 변환할 수 있는 유형이어야 합니다.

class rb.FanoutClient(hosts, Connection_pool, max_concurrency=None, auto_batch=True)

이는 MappingClient와 유사하게 작동하지만 라우터를 사용하여 호스트를 찾는 대신 수동으로 지정된 모든 호스트에 명령을 보냅니다.

결과는 호스트 ID를 기준으로 사전에 누적됩니다.

매개변수는 Cluster.fanout()을 참조하세요.

  • execute_command(*args, **options)

명령을 실행하고 구문 분석된 응답을 반환합니다.

  • target(hosts)

통화를 위해 일시적으로 클라이언트 위치를 변경합니다. 이는 단일 호출에 대해 호스트 하위 집합을 처리해야 하는 경우에 유용합니다.

  • target_key(key)

임시로 클라이언트를 재배치하여 특정 키가 라우팅되는 하나의 호스트로 특별히 라우팅된 호출을 만듭니다. 이 경우 Promise의 결과는 사전이 아닌 호스트 값일 뿐입니다.

버전 1.3의 새로운 기능.

Promise

class rb.Promise

Promise 객체용 ES6 API를 미러링하려고 시도하는 Promise 객체입니다. ES6의 Promise와 달리 이 Promise는 기본 값에 대한 직접 액세스도 제공하며 이 Promise는 외부에서 해결될 수 있기 때문에 정적 메서드 이름이 약간 다릅니다.

  • static all(iterable_or_dict)

전달된 모든 Promise가 해결되면 Promise가 해결됩니다. Promise 목록이나 Promise 사전을 전달할 수 있습니다.

  • done(on_success=None, on_failure=None)

Promise에 콜백을 추가하고 Promise를 반환하세요.

  • is_pending

약속이 아직 보류 중이면 True이고, 그렇지 않으면 False입니다.

  • is_rejected

약속이 거부되면 True이고, 그렇지 않으면 False입니다.

  • is_resolved

Promise가 해결되면 True이고, 그렇지 않으면 False입니다.

  • reason

이 약속이 거부된 경우의 이유입니다.

  • reject(reason)

주어진 이유를 사용하여 약속을 거부합니다.

  • static failed(reason)

특정 값으로 거부되는 Promise 객체를 생성합니다.

  • resolve(value)

주어진 값으로 Promise를 해결합니다.

  • staticsolved(value)

특정 값으로 해결되는 Promise 객체를 생성합니다.

  • then(success=None, failure=None)

Promise에 성공 및/또는 실패 콜백을 추가하는 유틸리티 메서드로, 프로세스에서 다른 Promise도 반환합니다.

  • value

이 약속이 해결될 경우 유지되는 가치입니다.

Routers

class rb.BaseRouter(cluster)

모든 경로의 기본 클래스입니다. 사용자 정의 경로를 구현하려는 경우 이것이 하위 클래스입니다.

  • cluster

는 이 라우터가 속한 클러스터를 다시 나타냅니다.

  • get_host_for_command(command, args)

이 명령을 실행해야 하는 호스트를 반환합니다.

  • get_host_for_key(key)

라우팅을 실행하고 대상의 호스트 ID를 반환합니다.

하위 클래스에서 이를 구현해야 합니다.

  • get_key(command, args)

명령 연산의 키를 반환합니다.

class rb.ConpersistHashingRouter(cluster)

일관적인 해싱 알고리즘을 기반으로 host_id의 라우터를 반환합니다. 일관된 해싱 알고리즘은 키 매개변수가 제공되는 경우에만 작동합니다.

라우터에서는 호스트에 간격이 없어야 합니다. 즉, N 호스트의 ID 범위는 0에서 N-1입니다.

  • get_host_for_key(key)

라우팅을 실행하고 대상의 호스트 ID를 반환합니다.

하위 클래스에서 이를 구현해야 합니다.

class rb.PartitionRouter(cluster)

단순한 crc32 % node_count 설정만을 기반으로 명령을 개별적으로 단일 노드로 라우팅하는 간단한 라우터입니다.

라우터에서는 호스트에 간격이 없어야 합니다. 즉, N 호스트의 ID 범위는 0에서 N-1입니다.

  • get_host_for_key(key)

执行路由并返回目标的 host_id。

子类需要实现这一点。

exception rb.UnroutableCommand

如果发出的命令无法通过 router 路由到单个主机,则引发。

Testing

class rb.testing.TestSetup(servers=4, databases_each=8, server_executable='redis-server')

测试设置是生成多个 redis 服务器进行测试并自动关闭它们的便捷方式。这可以用作 context manager 来自动终止客户端。

  • rb.testing.make_test_cluster(*args, **kwargs)

用于创建测试设置然后从中创建 cluster 的便捷快捷方式。这必须用作 context manager:

from rb.testing import make_test_cluster
with make_test_cluster() as cluster:
...

위 내용은 Redis용 비복제 샤딩을 구현하는 Python 라이브러리인 Rb(redis blaster)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 51cto.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제