def __init__(self, hash_algorithm='ketama', *args, **kwargs): super(MemcacheClient, self).__init__(*args, **kwargs) if hash_algorithm in self.available_algorithms: self.hash_algorithm_index = self.available_algorithms.index( hash_algorithm) if hash_algorithm == 'ketama': self.consistent_hash_manager = HashRing(nodes=self.servers) else: self.consistent_hash_manager = None else: raise Exception( "The algorithm \"%s\" is not implemented for this client. The " "options are \"%s\"" "" % (hash_algorithm, " or ".join(self.available_algorithms)))
def process(udp_clients): hash_ring = HashRing(2, 64, udp_clients) hash_ring.assign_nodes() hash_codes = set() # PUT all users. i = 0 for u in USERS: data_bytes, key = serialize_PUT(u) nodes_to_send = hash_ring.get_node(key) for n in nodes_to_send: resp = n.send(data_bytes) if i != 0: print(f' REPLICA PUT Response from server {n.port} is {resp}') else: print(f' ORIGINAL PUT Response from server {n.port} is {resp}') hash_codes.add(str(resp.decode())) i += 1 print( f"Number of Users={len(USERS)}\nNumber of Users Cached={len(hash_codes)}" ) # GET all users. for hc in hash_codes: print(hc) data_bytes, key = serialize_GET(hc) nodes_to_send = hash_ring.get_node(key) i = 0 for n in nodes_to_send: resp = n.send(data_bytes) if i != 0: print(f'REPLICA GET Response from server {n.port} is {resp}') else: print(f'ORIGINAL GET Response from server {n.port} is {resp}') i += 1
def __init__(self, hash_algorithm="ketama", *args, **kwargs): super(CustomMemcacheClient, self).__init__(*args, **kwargs) if hash_algorithm in self.available_algorithms: self.hash_algorithm_index = self.available_algorithms.index(hash_algorithm) if hash_algorithm == "ketama": self.consistent_hash_manager = HashRing(nodes=self.servers) else: self.consistent_hash_manager = None else: raise Exception( 'The algorithm "%s" is not implemented for this client. The ' 'options are "%s"' "" % (hash_algorithm, " or ".join(self.available_algorithms)) )
def __init__(self, hash_algorithm='ketama', *args, **kwargs): super(MemcacheClient, self).__init__(*args, **kwargs) if hash_algorithm in self.available_algorithms: self.hash_algorithm_index = self.available_algorithms.index( hash_algorithm) if hash_algorithm == 'ketama': self.consistent_hash_manager = HashRing(nodes=self.servers) else: self.consistent_hash_manager = None else: raise Exception( "The algorithm \"%s\" is not implemented for this client. The " "options are \"%s\"" "" % (hash_algorithm, " or ".join(self.available_algorithms)) )
class MemcacheClient(memcache.Client): """ A memcache subclass. It currently allows you to add a new host at run time. """ available_algorithms = ['ketama', 'modulo'] hash_algorithm_index = 0 def __init__(self, hash_algorithm='ketama', *args, **kwargs): super(MemcacheClient, self).__init__(*args, **kwargs) if hash_algorithm in self.available_algorithms: self.hash_algorithm_index = self.available_algorithms.index( hash_algorithm) if hash_algorithm == 'ketama': self.consistent_hash_manager = HashRing(nodes=self.servers) else: self.consistent_hash_manager = None else: raise Exception( "The algorithm \"%s\" is not implemented for this client. The " "options are \"%s\"" "" % (hash_algorithm, " or ".join(self.available_algorithms)) ) def _get_server(self, key): """ Returns the most likely server to hold the key """ if self.hash_algorithm == 'ketama': servers_generator = self.consistent_hash_manager.get_nodes(key) for server in servers_generator: if server.connect(): return server, key return None, None else: return super(MemcacheClient, self)._get_server(key) def add_server(self, server): """ Adds a host at runtime to client """ # when no reliable (modulo) consistent hash algorithm if not self.consistent_hash_manager: raise Exception("The current consistent hash algorithm (\"%s\") is" " not reliable for adding a new server" "" % self.hash_algorithm) # Create a new host entry server = memcache._Host( server, self.debug, dead_retry=self.dead_retry, socket_timeout=self.socket_timeout, flush_on_reconnect=self.flush_on_reconnect ) # Add this to our server choices self.servers.append(server) for _i in range(server.weight): self.buckets.append(server) # Adds this node to the circle if self.consistent_hash_manager: self.consistent_hash_manager.add_node(server)
class MemcacheClient(memcache.Client): """ A memcache subclass. It currently allows you to add a new host at run time. Sadly, this truely messes with the our keys. I.E. Adding a host at runtime effectively wipes our cache all together...Wonder why? """ available_algorithms = ['ketama', 'modulo'] hash_algorithm_index = 0 def __init__(self, hash_algorithm='ketama', *args, **kwargs): super(MemcacheClient, self).__init__(*args, **kwargs) if hash_algorithm in self.available_algorithms: self.hash_algorithm_index = self.available_algorithms.index( hash_algorithm) if hash_algorithm == 'ketama': self.consistent_hash_manager = HashRing(nodes=self.servers) else: self.consistent_hash_manager = None else: raise Exception( "The algorithm \"%s\" is not implemented for this client. The " "options are \"%s\"" "" % (hash_algorithm, " or ".join(self.available_algorithms)) ) def _get_server(self, key): """ Returns the most likely server to hold the key """ if self.hash_algorithm == 'ketama': """ Basic concept of the Implementation of ketama algorithm e.g. ring = {100:server1, 110:server2, 120:server3, 140:server4} If the hash of the current key is 105, it server will be the next bigger integer in the ring which is 110 (server2) If a server is added on position 108 the key will be now allocated to it and not to server 110. Otherwise if the server on position 110 is removed the key will now belong to de server 120. If there's no bigger integer position in the ring then the hash of the key, it will take the first server from the ring. """ # The variable "servers" is the list of the servers in the ring # starting from the next bigger integer to the hash of the key, # till it finds the one that holds the key servers_generator = self.consistent_hash_manager.get_nodes(key) for server in servers_generator: if server.connect(): return server, key return None, None else: return super(MemcacheClient, self)._get_server(key) def add_server(self, server): """ Adds a host at runtime to client """ # Uncomment this to protect the Client from adding a server in case # there's no reliable consistent hash algorithm such as MODULO """ if not self.consistent_hash_manager: raise Exception("The current consistent hash algorithm (\"%s\") is" " not reliable for adding a new server" "" % self.hash_algorithm) """ # Create a new host entry server = memcache._Host( server, self.debug, dead_retry=self.dead_retry, socket_timeout=self.socket_timeout, flush_on_reconnect=self.flush_on_reconnect ) # Add this to our server choices self.servers.append(server) """This for statement will ensure that a server with a bigger weight will have more copies into the buckets increasing it's probability to be retrieved. """ for i in range(server.weight): self.buckets.append(server) # Adds this node to the circle if self.consistent_hash_manager: self.consistent_hash_manager.add_node(server) @property def hash_algorithm(self): return self.available_algorithms[self.hash_algorithm_index]
class CustomMemcacheClient(memcache.Client): """ A memcache subclass. It currently allows you to add a new host at run time. """ available_algorithms = ['ketama', 'modulo'] hash_algorithm_index = 0 def __init__(self, hash_algorithm='ketama', *args, **kwargs): super(CustomMemcacheClient, self).__init__(*args, **kwargs) self.hash_algorithm = hash_algorithm if hash_algorithm in self.available_algorithms: self.hash_algorithm_index = self.available_algorithms.index( hash_algorithm) if hash_algorithm == 'ketama': self.consistent_hash_manager = HashRing(nodes=self.servers) else: self.consistent_hash_manager = None else: raise Exception( "The algorithm \"%s\" is not implemented for this client. The " "options are \"%s\"" "" % (hash_algorithm, " or ".join(self.available_algorithms))) def _get_server(self, key): """ Returns the most likely server to hold the key """ if self.hash_algorithm == 'ketama': """ Basic concept of the Implementation of ketama algorithm e.g. ring = {100:server1, 110:server2, 120:server3, 140:server4} If the hash of the current key is 105, it server will be the next bigger integer in the ring which is 110 (server2) If a server is added on position 108 the key will be now allocated to it and not to server 110. Otherwise if the server on position 110 is removed the key will now belong to de server 120. If there's no bigger integer position in the ring then the hash of the key, it will take the first server from the ring. """ # The variable "servers" is the list of the servers in the ring # starting from the next bigger integer to the hash of the key, # till it finds the one that holds the key servers_generator = self.consistent_hash_manager.get_nodes(key) for server in servers_generator: if server.connect(): #print server.address[1] return server, key return None, None else: return super(CustomMemcacheClient, self)._get_server(key) def add_server(self, server): """ Adds a host at runtime to client """ # Uncomment this to protect the Client from adding a server in case # there's no reliable consistent hash algorithm such as MODULO """ if not self.consistent_hash_manager: raise Exception("The current consistent hash algorithm (\"%s\") is" " not reliable for adding a new server" "" % self.hash_algorithm) """ # Create a new host entry server = memcache._Host(server, self.debug, dead_retry=self.dead_retry, socket_timeout=self.socket_timeout, flush_on_reconnect=self.flush_on_reconnect) # Add this to our server choices self.servers.append(server) """This for statement will ensure that a server with a bigger weight will have more copies into the buckets increasing it's probability to be retrieved. """ for i in range(server.weight): self.buckets.append(server) # Adds this node to the circle if self.consistent_hash_manager: self.consistent_hash_manager.add_node(server) @property def hash_algorithm(self): return self.available_algorithms[self.hash_algorithm_index]