Redis
 sql >> Teknologi Basis Data >  >> NoSQL >> Redis

Cara Memperbaiki Slot Hash Miring di Redis

Di Redis, unit distribusi utama adalah slot hash. Versi redis terdistribusi - termasuk Redis Cluster open source, Redis Enterprise komersial, dan bahkan AWS ElastiCache - hanya dapat memindahkan data 1 slot pada satu waktu.

Ini mengarah ke masalah yang menarik - slot miring. Bagaimana jika satu slot (atau beberapa slot) akhirnya memiliki sebagian besar data?

Apakah itu mungkin?

Redis memutuskan hash-slot untuk kunci menggunakan algoritma yang dipublikasikan dengan baik. Algoritme ini biasanya akan memastikan bahwa kunci terdistribusi dengan baik.

Tetapi pengembang dapat memengaruhi algoritme dengan menentukan tag hash . Tag hash adalah bagian dari kunci yang diapit kurung kurawal {...} . Ketika tag hash ditentukan, tag tersebut akan digunakan untuk menentukan slot hash.

Hash-tag di redis adalah apa yang kebanyakan database sebut sebagai kunci partisi. Jika Anda memilih kunci partisi yang salah, Anda akan mendapatkan slot yang miring.

Sebagai contoh, jika kunci Anda seperti {users}:1234 dan {users}:5432 , redis akan menyimpan semua pengguna di slot hash yang sama.

Apa perbaikannya?

Perbaikannya adalah secara konseptual sederhana - Anda perlu mengganti nama kunci untuk menghapus tag hash yang salah. Jadi ganti nama {users}:1234 untuk users:{1234} atau bahkan users:1234 harus melakukan triknya…

… kecuali bahwa perintah rename tidak berfungsi di redis cluster.

Jadi satu-satunya jalan keluar adalah membuang kuncinya terlebih dahulu, lalu mengembalikannya dengan nama baru.

Berikut tampilannya dalam kode:



from redis import StrictRedis
try:
    from itertools import izip_longest
except:
    from itertools import zip_longest as izip_longest


def get_batches(iterable, batch_size=2, fillvalue=None):
    """
    Chunks a very long iterable into smaller chunks of `batch_size`
    For example, if iterable has 9 elements, and batch_size is 2,
    the output will be 5 iterables - each of length 2. 
    The last iterable will also have 2 elements, 
    but the 2nd element will be `fillvalue`
    """
    args = [iter(iterable)] * batch_size
    return izip_longest(fillvalue=fillvalue, *args)


def migrate_keys(allkeys, host, port, password=None):
    db = 0
    red = StrictRedis(host=host, port=port, password=password)

    batches = get_batches(allkeys)
    for batch in batches:
        pipe = red.pipeline()
        keys = list(batch)
        for key in keys:
            if not key:
                continue
            pipe.dump(key)
            
        response = iter(pipe.execute())
        # New pipeline to run the restore command
        pipe = red.pipeline(transaction=False)
        for key in keys:
            if not key:
                continue
            obj = next(response)
            new_key = "restored." + key
            pipe.restore(new_key, 0, obj)

        pipe.execute()


if __name__ == '__main__':
    allkeys = ['users:18245', 'users:12328:answers_by_score', 'comments:18648']
    migrate_keys(allkeys, host="localhost", port=6379)


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Transaksi dan laporan tontonan di Redis

  2. Saga MassTransit dengan ketekunan Redis memberi Metode Accpet tidak memiliki pengecualian implementasi

  3. Redis:Amazon EC2 vs Elasticache

  4. Bagaimana cara menyimpan JSON Bersarang Kompleks di Redis menggunakan Python

  5. Bagaimana cara memberi tahu Klien di mana master Redis baru menggunakan Sentinel