Redis
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> Redis

Làm thế nào để khắc phục các khe băm bị thiếu trong Redis

Trong Redis, đơn vị phân phối chính là một rãnh băm. Các phiên bản phân tán của redis - bao gồm Redis Cluster mã nguồn mở, Redis Enterprise thương mại và thậm chí AWS ElastiCache - chỉ có thể di chuyển quanh vùng dữ liệu tại một thời điểm.

Điều này dẫn đến một vấn đề thú vị - các khe cắm mặt lop. Điều gì sẽ xảy ra nếu một vùng (hoặc một vài vùng) có hầu hết dữ liệu?

Điều đó có khả thi không?

Redis quyết định vị trí băm cho một khóa bằng cách sử dụng một thuật toán được xuất bản tốt. Thuật toán này thường sẽ đảm bảo rằng các khóa được phân phối tốt.

Nhưng các nhà phát triển có thể tác động đến thuật toán bằng cách chỉ định một thẻ băm . Thẻ băm là một phần của khóa được đặt trong dấu ngoặc nhọn {...} . Khi một thẻ băm được chỉ định, nó sẽ được sử dụng để quyết định vị trí băm.

Thẻ băm trong redis là thứ mà hầu hết các cơ sở dữ liệu gọi là khóa phân vùng. Nếu bạn chọn một khóa phân vùng sai, bạn sẽ nhận được các khe bị lệch.

Ví dụ:nếu các khóa của bạn giống như {users}:1234{users}:5432 , redis sẽ lưu trữ tất cả người dùng trong cùng một vùng băm.

Cách khắc phục là gì?

Cách khắc phục là về mặt khái niệm đơn giản - bạn cần đổi tên khóa để xóa thẻ băm không chính xác. Vì vậy, đổi tên {users}:1234 tới người dùng users:{1234} hoặc thậm chí users:1234 nên thực hiện thủ thuật…

… Ngoại trừ việc lệnh đổi tên không hoạt động trong cụm redis.

Vì vậy, cách duy nhất là trước tiên hãy kết xuất khóa và sau đó khôi phục nó với tên mới.

Đây là cách nó trông như thế nào trong mã:



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. Đăng ký nhiều kênh với cùng một chủ đề Jedis

  2. Làm cách nào để triển khai tính năng hết thời gian chờ pubsub của redis?

  3. nginx uwsgi websockets 502 Bad Gateway ngược dòng kết nối bị đóng sớm trong khi đọc tiêu đề phản hồi từ ngược dòng

  4. Redis Keyspace Notifications với flushdb

  5. Làm việc với hai phiên bản redis riêng biệt với sidekiq?