Поддерживает ли python-memcached согласованное хеширование и двоичный протокол? - PullRequest
4 голосов
/ 11 апреля 2010

Python-memcached - официальный поддерживаемый драйвер memcached для Django.

Поддерживает ли он

  1. Согласованное хеширование
  2. Двоичный протокол

Если да, как мне использовать эти функции в Django?Я не смог найти никакой документации.

Ответы [ 6 ]

2 голосов
/ 11 апреля 2010

Глядя на метод _get_server в python-memcached v1.45, кажется, что он не использует согласованное хеширование, а просто hash % len(buckets).

То же самое относится и к двоичному протоколу, python-memcacheнасколько я вижу в источнике, использует только текстовые команды.

1 голос
/ 10 мая 2017

Пожалуйста, проверьте этот пример реализации согласованного хэширования на python.

принцип реализации : представьте себе непрерывный круг с несколькими реплицированными точками сервера, распределенными по нему. Когда мы добавляем новый сервер, 1 / n от общего ключи кеша будут потеряны

 '''consistent_hashing.py is a simple demonstration of consistent
hashing.'''

import bisect
import hashlib

class ConsistentHash:
  '''

  To imagine it is like a continnum circle with a number of replicated
  server points spread across it. When we add a new server, 1/n of the total
  cache keys will be lost. 

  consistentHash(n,r) creates a consistent hash object for a 
  cluster of size n, using r replicas. 

  It has three attributes. num_machines and num_replics are
  self-explanatory.  hash_tuples is a list of tuples (j,k,hash), 
  where j ranges over machine numbers (0...n-1), k ranges over 
  replicas (0...r-1), and hash is the corresponding hash value, 
  in the range [0,1).  The tuples are sorted by increasing hash 
  value.

  The class has a single instance method, get_machine(key), which
  returns the number of the machine to which key should be 
  mapped.'''
  def __init__(self,replicas=1):
      self.num_replicas = replicas

  def setup_servers(self,servers=None):
    hash_tuples = [(index,k,my_hash(str(index)+"_"+str(k))) \
               for index,server in enumerate(servers)
               for k in range(int(self.num_replicas) * int(server.weight)) ]
    self.hash_tuples=self.sort(hash_tuples);

  def sort(self,hash_tuples):
    '''Sort the hash tuples based on just the hash values   '''
    hash_tuples.sort(lambda x,y: cmp(x[2],y[2]))
    return hash_tuples

  def add_machine(self,server,siz):
    '''This mathod adds a new machine. Then it updates the server hash
     in the continuum circle '''
    newPoints=[(siz,k,my_hash(str(siz)+"_"+str(k))) \
                   for k in range(self.num_replicas*server.weight)]
    self.hash_tuples.extend(newPoints)
    self.hash_tuples=self.sort(self.hash_tuples);



  def get_machine(self,key):
    '''Returns the number of the machine which key gets sent to.'''
    h = my_hash(key)
    # edge case where we cycle past hash value of 1 and back to 0.
    if h > self.hash_tuples[-1][2]: return self.hash_tuples[0][0]
    hash_values = map(lambda x: x[2],self.hash_tuples)
    index = bisect.bisect_left(hash_values,h)
    return self.hash_tuples[index][0]

def my_hash(key):
  '''my_hash(key) returns a hash in the range [0,1).'''
  return (int(hashlib.md5(key).hexdigest(),16) % 1000000)/1000000.0
1 голос
/ 07 мая 2010

Вы можете использовать это: http://amix.dk/blog/post/19370

Он инкапсулирует класс Client в python-memcache, поэтому ключи распределяются с использованием согласованного хеширования.

РЕДАКТИРОВАТЬ - я копаю python-memcached 1.4.5 исходный код, и похоже, что он на самом деле может поддерживать согласованное хеширование. Соответствующий код:

from binascii import crc32   # zlib version is not cross-platform
def cmemcache_hash(key):
    return((((crc32(key) & 0xffffffff) >> 16) & 0x7fff) or 1)
serverHashFunction = cmemcache_hash

-- SNIP --

def _get_server(self, key):
    if isinstance(key, tuple):
        serverhash, key = key
    else:
        serverhash = serverHashFunction(key)

    for i in range(Client._SERVER_RETRIES):
        server = self.buckets[serverhash % len(self.buckets)]
        if server.connect():
            #print "(using server %s)" % server,
            return server, key
        serverhash = serverHashFunction(str(serverhash) + str(i))
    return None, None

Исходя из этого кода, похоже, что он реализует алгоритм, если только cmemcache_hash не является значимым именем и не является реальным алгоритмом. (теперь вышедший на пенсию cmemcache выполняет согласованное хеширование)

Но я думаю, что OP имеет в виду более «устойчивое» согласованное хеширование, например libketama . Я не думаю, что есть какое-то решение для этого, похоже, вам нужно закатать рукава, скомпилировать / установить более продвинутую библиотеку memcached, такую ​​как pylibmc , и написать собственный бэкэнд Django, который использует это вместо python-memcached.

Во всяком случае, в любом случае при добавлении / удалении сегментов в пул произойдет некоторое перераспределение ключей (даже при использовании libketama, чуть меньше, чем при использовании других алгоритмов)

0 голосов
/ 15 сентября 2015

Я использовал алгоритм согласованного хеширования. Потерянные ключи составляют 1 / n от общего количества ключей. Это означает, что успешный выбор ключа будет 6/7 * 100 около 85%. здесь

0 голосов
/ 05 мая 2014

Если вам нужно решение «подключи и работай» для django, используйте django-memcached-hashring: https://github.com/jezdez/django-memcached-hashring.

Это адаптер для django.core.cache.backends.memcached.MemcachedCache и библиотеки hash_ring.

0 голосов
/ 19 февраля 2014

Теперь vbucket подходит для разрешения согласованного хеширования с наименьшим влиянием на ошибки в кеше.

...