Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Rb (redis blaster), perpustakaan Python yang melaksanakan sharding tidak direplikasi untuk Redis

Rb (redis blaster), perpustakaan Python yang melaksanakan sharding tidak direplikasi untuk Redis

WBOY
WBOYke hadapan
2023-04-11 19:27:271643semak imbas

Rb, redis blaster, ialah perpustakaan yang melaksanakan sharding tidak direplikasi untuk redis. Ia melaksanakan sistem penghalaan tersuai di atas python redis, membolehkan anda menyasarkan pelayan berbeza secara automatik tanpa perlu mengarahkan permintaan ke nod individu secara manual.

Ia tidak melaksanakan semua ciri redis, mahupun cuba untuk melakukannya. Anda sentiasa boleh menyambungkan klien kepada hos tertentu, tetapi kebanyakannya menganggap operasi anda terhad kepada operasi kunci/nilai asas yang boleh dialihkan secara automatik ke nod yang berbeza.

Apa yang boleh anda lakukan:

  • Lakukan operasi kekunci tunggal secara automatik pada hos.
  • Laksanakan arahan pada semua atau beberapa nod.
  • Laksanakan semua ini secara selari.

Pasang

rb tersedia pada PyPI dan boleh dipasang dari sana:

$ pip install rb

Konfigurasikan

Mulakan dengan rb Sangat Mudah. Jika anda pernah menggunakan py-redis sebelum ini, anda akan berasa seperti di rumah sendiri. Perbezaan utama ialah daripada menyambung kepada hos tunggal, kluster dikonfigurasikan untuk menyambung kepada berbilang:

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',
})

Dalam kes ini, kami menyediakannya pada empat proses pelayan berbeza pada 8 nod hos yang sama . Parameter hos ialah peta hos untuk disambungkan. Kunci kamus ialah ID hos (integer), dan nilainya ialah kamus parameter. host_defaults ialah kamus lalai pilihan yang diisi untuk semua hos. Ini berguna jika anda ingin berkongsi beberapa lalai biasa yang berulang (dalam kes ini, semua hos bersambung ke localhost).

Dalam konfigurasi lalai, PartitionRouter digunakan untuk penghalaan.

Penghalaan

Sekarang kluster dibina, kita boleh menggunakan Cluster.get_routing_client() untuk mendapatkan klien redis yang secara automatik akan menghalakan setiap arahan ke nod redis yang betul:

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

Pelanggan ini berfungsi sangat serupa dengan pyredis StrictClient standard, perbezaan utama ialah ia hanya boleh melaksanakan arahan yang melibatkan hanya satu kunci.

Walau bagaimanapun, operasi asas ini dijalankan secara bersiri. Apa yang menjadikan rb berguna ialah ia boleh membina saluran paip redis secara automatik dan menghantar pertanyaan kepada banyak hos secara selari. Walau bagaimanapun, ini mengubah sedikit penggunaan, kerana kini nilainya tidak tersedia dengan serta-merta:

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

Walaupun ia kelihatan serupa setakat ini, daripada menyimpan nilai sebenar dalam kamus hasil, objek Promise disimpan . Apabila pengurus konteks peta tamat, ia dijamin telah dilaksanakan, anda boleh mengakses sifat Promise.value untuk mendapatkan nilai:

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

Jika anda ingin menghantar arahan kepada semua hos yang mengambil bahagian (cth. memadam pangkalan data), anda boleh menggunakan kaedah Cluster.all():

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

Jika anda melakukan ini, nilai janji ialah kamus dengan ID hos sebagai kunci dan hasilnya sebagai nilai. Contohnya:

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'])

Untuk menyasarkan hos tertentu secara khusus, anda boleh menggunakan Cluster.fanout() untuk menerima senarai ID hos untuk menghantar arahan kepada.

API

Ini adalah rujukan lengkap kepada API awam. Ambil perhatian bahawa perpustakaan ini memanjangkan perpustakaan Python redis, jadi beberapa kelas mempunyai lebih banyak fungsi, anda perlu menyemak perpustakaan py-redis.

Kluster

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

cluster is behind rb objek teras. Ia disimpan ke kumpulan sambungan nod individu dan boleh dikongsi di lokasi pusat semasa aplikasi sedang berjalan.

Contoh asas kluster pada empat kejadian redis dengan penghala lalai:

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

hos ialah kamus hos yang memetakan nombor ID hos kepada parameter konfigurasi. Parameter sepadan dengan tandatangan fungsi add_host(). Nilai lalai untuk parameter ini diambil daripada host_defaults. Untuk mengatasi kelas pool, gunakan parameter pool_cls dan pool_options. Perkara yang sama berlaku untuk router_cls dan router_options. Pilihan pool berguna untuk menetapkan tamat masa soket dan parameter yang serupa.

  • add_host(host_id=None, host='localhost', port=6379, unix_socket_path=None, db=0, password=None, ssl=False, ssl_options=None)

Tambahkan hos baharu pada kelompok. Ini hanya benar-benar berguna untuk ujian unit, kerana biasanya hos ditambah melalui pembina dan tidak mungkin masuk akal untuk berubah selepas kali pertama kelompok digunakan.

  • semua(masa tamat=Tiada, max_concurrency=64, auto_batch=True)

Beri perhatian kepada semua hos. Jika tidak sama dengan fanout().

Contoh:

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

Memutuskan semua sambungan ke kolam dalaman.

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

Pada masa yang sama, laksanakan satu siri arahan yang dikaitkan dengan kunci penghalaan pada gugusan Redis dan kembalikan pemetaan baharu, di mana Nilai ialah senarai hasil yang sepadan dengan arahan di lokasi yang sama. Contohnya:

>>> cluster.execute_commands({
... 'foo': [
... ('PING',),
... ('TIME',),
... ],
... 'bar': [
... ('CLIENT', 'GETNAME'),
... ],
... })
{'bar': [<Promise None>],
 'foo': [<Promise True>, <Promise (1454446079, 418404)>]}
  • Arahan yang merupakan contoh redis.client.Script akan terlebih dahulu menyemak kewujudannya pada nod sasaran dan kemudian dimuatkan pada sasaran sebelum pelaksanaan, dan boleh disisipkan dengan arahan lain:
>>> 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']]>]}

Secara dalaman, FanoutClient digunakan untuk mengeluarkan arahan.

  • 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 自动定位单个节点。

Lihat Cluster.map() untuk parameter.

  • batal()

Batalkan semua permintaan tertunggak.

  • execute_command(*args, **options)

Laksanakan arahan dan kembalikan respons yang dihuraikan

  • join(timeout=None)

Tunggu sehingga semua respons tertunggak kembali atau tamat masa

  • mget(keys, *args)

Kembalikan nilai dalam yang sama perintah sebagai kunci Senarai

  • mset(*args, **kwargs)

Tetapkan kunci/nilai mengikut pemetaan. Peta ialah kamus pasangan kunci/nilai. Kedua-dua kunci dan nilai hendaklah rentetan atau jenis yang boleh ditukar kepada rentetan melalui str().

kelas rb.FanoutClient(hosts, connection_pool, max_concurrency=None, auto_batch=True)

Ini berfungsi sama seperti MappingClient, tetapi bukannya menggunakan penghala untuk mencari hos, ia meletakkan arahan Dihantar kepada semua hos yang ditentukan secara manual.

Hasil terkumpul dalam kamus yang dikunci oleh host_id.

Lihat Cluster.fanout() untuk parameter.

  • execute_command(*args, **options)

Laksanakan arahan dan kembalikan respons yang dihuraikan

  • target(hosts)

Pindahkan klien buat sementara waktu untuk panggilan. Ini berguna apabila subset hos mesti diproses untuk satu panggilan.

  • target_key(key)

Sasarkan semula klien buat sementara waktu untuk membuat panggilan yang dihalakan secara khusus kepada satu hos yang mana kunci yang diberikan dihalakan. Dalam kes ini, hasil janji hanyalah nilai hos dan bukannya kamus.

Ciri baharu dalam versi 1.3.

Promise

class rb.Promise

Objek Promise yang cuba mencerminkan API ES6 untuk objek Promise. Tidak seperti Janji ES6, Janji ini juga menyediakan akses terus kepada nilai asas, dan ia mempunyai nama kaedah statik yang sedikit berbeza kerana Janji ini boleh diselesaikan secara luaran.

  • statik semua(iterable_or_dict)

Janji diselesaikan apabila semua janji yang diluluskan telah diselesaikan. Anda boleh lulus senarai janji atau kamus janji.

  • done(on_success=None, on_failure=None)

Tambahkan beberapa panggilan balik pada Promise dan kembalikan Promise.

  • sedang_bertangguh

Benar jika janji masih tertangguh, Palsu sebaliknya.

  • ditolak

Betul jika janji ditolak, Palsu sebaliknya.

  • sudah_selesai

Benar jika janji ditepati, Palsu sebaliknya.

  • alasan

Sebab janji ini jika ditolak.

  • tolak(alasan)

Tolak janji dengan alasan yang diberikan.

  • statik ditolak(sebab)

Mencipta objek janji yang ditolak dengan nilai tertentu.

  • selesaikan(nilai)

Selesaikan janji dengan nilai yang diberikan.

  • statik diselesaikan(nilai)

Mencipta objek janji yang diselesaikan dengan nilai tertentu.

  • kemudian(success=None, failure=None)

Kaedah utiliti untuk menambah panggilan balik kejayaan dan/atau kegagalan pada Promise, yang juga akan dikembalikan semasa proses Janji lain.

  • nilai

Nilai yang dipegang oleh janji ini jika ia diselesaikan.

Penghala

kelas rb.BaseRouter(kluster)

Kelas asas untuk semua laluan. Jika anda ingin melaksanakan laluan tersuai, ini ialah subkelas anda.

  • kluster

merujuk kembali kepada Kluster yang menjadi milik penghala ini.

  • get_host_for_command(command, args)

Mengembalikan hos yang mana arahan ini harus dilaksanakan.

  • get_host_for_key(key)

Laksanakan laluan dan kembalikan host_id sasaran.

Subkelas perlu melaksanakan perkara ini.

  • get_key(command, args)

Mengembalikan kunci operasi arahan.

kelas rb.ConsistentHashingRouter(cluster)

Mengembalikan penghala host_id berdasarkan algoritma pencincangan yang konsisten. Algoritma pencincangan yang konsisten hanya berfungsi apabila parameter utama disediakan.

Penghala ini memerlukan hos tanpa celah, yang bermaksud bahawa ID hos N berjulat dari 0 hingga N-1.

  • get_host_for_key(key)

Laksanakan laluan dan kembalikan host_id sasaran.

Subkelas perlu melaksanakan perkara ini.

kelas rb.PartitionRouter(cluster)

Penghala mudah yang mengarahkan arahan secara individu ke satu nod berdasarkan tetapan crc32 % node_count yang ringkas.

Penghala ini memerlukan hos tanpa celah, yang bermaksud bahawa ID hos N berjulat dari 0 hingga 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:
...

Atas ialah kandungan terperinci Rb (redis blaster), perpustakaan Python yang melaksanakan sharding tidak direplikasi untuk Redis. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:51cto.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam