这一篇中我们实现了不通过zk来编写codis集群proxys的api,http://www.cnblogs.com/kangoroo/p/7481567.html

如果codis集群暴露zk给你的话,那么就方便了,探活和故障摘除与恢复codis集群都给你搞定了,你只需要监听zookeeper中实例的状态就好了。

下面看我的实现。

1、CodisByZKPool.py

这里通过zk读取并初始化pool_shards,简单说一下如何故障摘除和恢复

1)我们监听zk中节点状态改变,当发现某个实例对应的节点状态变化了,比如DELETE了,那么我们认为这个实例挂了,我们就会重新_create_pool刷新shards列表,摘除故障实例。

2)同样,当我们发现节点CREATE,就是新增了实例,或者实例从崩溃中恢复了,我们也会重新_create_pool刷新shards列表,新增实例。

# -*- coding:utf-8 -*-
import redis
import logging
from kazoo.client import KazooClient
from Podis import Podis
from PickUp import RandomPickUp, PickUp logger = logging.getLogger(__name__) class CodisByZKPool(object): def __init__(self, zk_config):
self._pool_shards = []
self.zk_config = zk_config
self.zk = self._init_zk() def _init_zk(self):
return KazooClient(hosts=self.zk_config.get('hosts'), timeout=self.zk_config.get('timeout')) def _create_pool(self):
try:
if not self.zk.connected:
self.zk.start()
address_list = self.zk.get_children(self.zk_config.get('path'), watch=self._watch_codis_instances)
for address in address_list:
host = address.split(':')[0]
port = address.split(':')[1]
self._pool_shards.append(
Podis(
redis.ConnectionPool(
host=host, port=port, db=0,
password=None,
max_connections=None
)
)
)
if len(self._pool_shards) == 0:
raise Exception('create pool failure!')
except Exception, ex:
raise
finally:
self.zk.stop() def _watch_codis_instances(self, event):
if event.type == "CREATED" and event.state == "CONNECTED":
self._create_pool()
elif event.type == "DELETED" and event.state == "CONNECTED":
self._create_pool()
elif event.type == "CHANGED" and event.state == "CONNECTED":
self._create_pool()
elif event.type == "CHILD" and event.state == "CONNECTED":
self._create_pool()
else:
logger.error('failure: not cover this event - %s'.format(event.type)) def get_connection(self, pick_up=None):
if isinstance(pick_up, PickUp):
codisPool = pick_up.pick_up(self._pool_shards)
else:
pick_up = RandomPickUp()
codisPool = pick_up.pick_up(self._pool_shards)
return codisPool def get_availables(self):
return self._pool_shards

2、负载均衡PickUp.py

上一篇一样,这里就不多说了。

# -*- coding:utf-8 -*-
import abc
import uuid
import threading class PickUp(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod
def __init__(self):
pass @abc.abstractmethod
def pick_up(self, pool_list):
return class RandomPickUp(PickUp):
def __init__(self):
PickUp.__init__(self) def pick_up(self, pool_list):
pool_size = len(pool_list)
index = abs(hash(uuid.uuid4())) % pool_size
pool = pool_list[index]
print "RandomPickUp, 拿到第", index, "个pool"
return pool class RoundRobinPickUp(PickUp): def __init__(self):
PickUp.__init__(self)
self.index = 0
self.round_robin_lock = threading.Lock() def pick_up(self, pool_list):
with self.round_robin_lock:
pool_size = len(pool_list)
self.index += 1
index = abs(self.index) % pool_size
pool = pool_list[index]
print "RoundRobinPickUp, 拿到第", index, "个pool"
return pool

3、配置文件

这里就只用zk_config就可以了,我们认为在zk中已经有所有的codisproxy实例的address了。

codis_config = {
'addrs': '100.90.186.47:3000,100.90.187.33:3000'
} zk_config = {
'hosts': '10.93.21.21:2181,10.93.18.34:2181,10.93.18.35:2181',
'timeout': 10,
'path': '/codis/instances'
}

4、链接类Podis.py

# -*- coding:utf-8 -*-
import redis
import logging
import traceback logger = logging.getLogger(__name__) def redis_getter(func):
def wrapper(*args, **kwargs):
try:
result = func(*args, **kwargs)
return result or None
except Exception, ex:
logger.error(traceback.format_exc())
raise
return wrapper def redis_setter(func):
def wrapper(*args, **kwargs):
try:
func(*args, **kwargs)
return True
except Exception, ex:
logger.error(traceback.format_exc())
raise
return wrapper class Podis(object): def __init__(self, pool):
self._connection = redis.StrictRedis(connection_pool=pool) @redis_getter
def ping(self):
return self._connection.ping() @redis_getter
def get(self, key):
return self._connection.get(key) @redis_setter
def set(self, key, value):
self._connection.set(key, value) @redis_setter
def lpush(self, key, *value):
self._connection.lpush(key, *value) @redis_getter
def lpop(self, key):
return self._connection.lpop(key) @redis_getter
def lrange(self, key, start, end):
return self._connection.lrange(key, start, end) @redis_setter
def sadd(self, key, *value):
self._connection.sadd(key, *value) @redis_setter
def srem(self, key, *value):
self._connection.srem(key, *value) @redis_getter
def zrange(self,key,start,end):
return self._connection.zrange(key,start,end) @redis_getter
def zrevrange(self,key,start,end):
return self._connection.zrevrange(key,start,end,withscores=True) @redis_getter
def zscore(self,key,*value):
return self._connection.zscore(key,value) @redis_setter
def zadd(self,key,score,*value):
self._connection.zadd(key,score,value) @redis_getter
def smembers(self, key):
return self._connection.smembers(key) @redis_getter
def hgetall(self, key):
return self._connection.hgetall(key) @redis_getter
def hget(self, key, name):
return self._connection.hget(key, name) @redis_getter
def hkeys(self, key):
return self._connection.hkeys(key) @redis_setter
def hset(self, key, name, value):
self._connection.hset(key, name, value) @redis_setter
def hmset(self, name, mapping):
self._connection.hmset(name, mapping) @redis_setter
def hdel(self, key, name):
self._connection.hdel(key, name) @redis_setter
def delete(self, *key):
self._connection.delete(*key) # codis不支持
@redis_getter
def keys(self, pattern):
return self._connection.keys(pattern) @redis_setter
def expire(self, key, time):
return self._connection.expire(key, time) @redis_getter
def ttl(self, key):
return self._connection.ttl(key)

5、例子

import sys
sys.path.append('../')
import time
import threading
from pycodis.CodisConfig import zk_config
from pycodis.CodisByZKPool import CodisByZKPool
from pycodis.PickUp import RoundRobinPickUp codis_pool1 = CodisByZKPool(zk_config)
print '------1-------'
pick_up1 = RoundRobinPickUp()
print '------2-------'
codis_pool2 = CodisByZKPool(zk_config)
print '------3-------'
pick_up2 = RoundRobinPickUp()
print '------4-------' def func(i):
for i in range(10):
podis1 = codis_pool1.get_connection(pick_up=pick_up1)
podis2 = codis_pool2.get_connection(pick_up=pick_up2)
podis1.delete(i)
podis2.delete(i)
time.sleep(1) thread_list = []
for i in range(100):
thread_list.append(threading.Thread(target=func, args=[i])) for thread in thread_list:
thread.setDaemon(True)
thread.start() time.sleep(10)

python codis集群客户端(二) - 基于zookeeper对实例创建与摘除的更多相关文章

  1. python codis集群客户端(一) - 基于客户端daemon探活与服务列表维护

    在使用codis时候,我们遇到的场景是,公司提供了HA的Proxy(例如N个),但是不暴露zookeeper(也就是说没有codis后端服务列表). 如果暴露zk的话,可以看这一篇,http://ww ...

  2. 七、Hadoop3.3.1 HA 高可用集群QJM (基于Zookeeper,NameNode高可用+Yarn高可用)

    目录 前文 Hadoop3.3.1 HA 高可用集群的搭建 QJM 的 NameNode HA Hadoop HA模式搭建(高可用) 1.集群规划 2.Zookeeper集群搭建: 3.修改Hadoo ...

  3. Dubbo+zookeeper构建高可用分布式集群(二)-集群部署

    在Dubbo+zookeeper构建高可用分布式集群(一)-单机部署中我们讲了如何单机部署.但没有将如何配置微服务.下面分别介绍单机与集群微服务如何配置注册中心. Zookeeper单机配置:方式一. ...

  4. Linux Redis集群搭建与集群客户端实现(Python)

    硬件环境 本文适用的硬件环境如下 Linux版本:CentOS release 6.7 (Final) Redis版本: Redis已经成功安装,安装路径为/home/idata/yangfan/lo ...

  5. 实战Centos系统部署Codis集群服务

    导读 Codis 是一个分布式 Redis 解决方案, 对于上层的应用来说, 连接到 Codis Proxy 和连接原生的 Redis Server 没有明显的区别 (不支持的命令列表), 上层应用可 ...

  6. Codis集群的搭建与使用

    一.简介 Codis是一个分布式的Redis解决方案,对于上层的应用来说,连接Codis Proxy和连接原生的Redis Server没有明显的区别(不支持的命令列表),上层应用可以像使用单机的Re ...

  7. Codis集群的搭建

    Codis集群的搭建与使用   一.简介 Codis是一个分布式的Redis解决方案,对于上层的应用来说,连接Codis Proxy和连接原生的Redis Server没有明显的区别(不支持的命令列表 ...

  8. [Big Data - Codis] Codis集群的搭建与使用

    一.简介 Codis是一个分布式的Redis解决方案,对于上层的应用来说,连接Codis Proxy和连接原生的Redis Server没有明显的区别(不支持的命令列表),上层应用可以像使用单机的Re ...

  9. JMS之——ActiveMQ 高可用与负载均衡集群安装、配置(ZooKeeper + LevelDB + Static discovery)

    一.说明 从 ActiveMQ 5.9 开始, ActiveMQ 的集群实现方式取消了传统的 Master-Slave 方式,增加了基于ZooKeeper + LevelDB 的 Master-Sla ...

随机推荐

  1. web服务的三大主流架构

    1.远程过程调用 2.服务导向架构 3.表述性状态转移 今天在自学Spring架构时貌似发现 rest的表现.与RPC方式的最大差别,SOA方式更加关注如何去连接服务而不是去特定某个实现的细节.而re ...

  2. 201521123084 《Java程序设计》第3周学习总结

    1. 本周学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识组织起来.请使用纸笔或者下面的工具画出本周学习到的知识点.截图或者拍照上传. 本周学习总结 ...

  3. oop学习 计算器类的规划

    类的学习 题目要求 采取面向对象的方法,四则运算自动出题软件,根据需求可以划分为几个类?每个类具有什么属性?每个类具有什么行为? 类与类之间是如何进行协作的?谁给谁发送消息?谁持有谁的引用? 该自动出 ...

  4. 201521123055 《Java程序设计》第5周学习总结

    1. 本章学习总结 2. 书面作业 Q1.代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误.并分析输出结果. 1. ...

  5. 201521123045 《Java程序设计》第5周学习总结

    第5周-继承.多态.抽象类与接口 1. 本周学习总结 2. 书面作业 Q1.代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试 ...

  6. 201521123008《Java程序设计》第二周实验总结

    本周学习总结 ① 数据类型,其中char是占用两个字节的内存空间,其他和以前学过的一样.除了十进制位,整型也可以用八进制或者十六进制表示.浮点型不精确. ②运算符,算术,赋值,逻辑,位运算. ③str ...

  7. 201521123080《Java程序设计》第9周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前 ...

  8. 201521123024 《java程序设计》 第12周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容.

  9. NA笔记

    常用配置命令 mstsc 远程桌面控制指令(在运行中输入) cmd 运行 copy running-config start 正在启动文件 copy running-config startup-ci ...

  10. Spring第九篇【Spring与Hibernate整合】

    前言 前面已经学习了如何使用Spring与Struts2进行整合,本博文主要讲解如何使用Spring对Hibernate进行整合 Spring和Hibernate整合的关键点: SessionFact ...