disgear是笔者参考solrcloud架构基于redis实现的分布式的缓存,支持数据切分到多台机器上,支持HA,支持读写分离和主节点失效自动选举,目前把它开放到github上,开放给大家

github:https://github.com/yangbutao/disgear

总体设计

1. 系统需求

1) 性能

内存操作,读写性能要求比较高

2) 数据量

支持数据切分,分为多个Shard,每个shard负责一定范围的数据

3) 伸缩性

当单个节点的数据量比较大的时,可以对该节点进行数据切分,分离成两部分,增加新的机器即可。

4) 可用性

系统不存在单点问题,缓存节点支持HA,master节点宕掉后,自动选举一个slave为主节点,对客户端透明

2. 设计说明

首先启动好所有的redis实例,每个redis实例有一个agent负责监控,agent ping redis实例的状态,agent 连接到zookeeper上创建/collections/collection1/leader_elect/shard1/election下的节点,监控比它小的节点,变化时更新leader节点。

当agent连接zookeeper超时或者agent ping redis实例超时,会删除zookeeper上的election下的节点(agent ping redis超时,调用zookeeper api删除节点)。

当ping到redis节点起来后,若检查到zookeeper上没有对应节点,则创建相应节点。

Leader(master)是缓存负责响应的节点,replica(slave)只负责同步leader的数据,当leader宕机后,提升replica为主节点。

以下是zookeeper上节点的相关说明:

/collections

|----collection1

|----leader_elect

----shard1[0-7ffffffff]      //节点启动时,一共需要分几个 分区,需要声明该节点属于哪个shard

---election         //参与选举的节点列表,竞争成为leader节   点,并更新leaders节点列表和clusterstate.json节点内容,并调用脚 本 更改redis的master slave配置

----10.1.1.21

----10.1.1.22

----shard2

---eclection

---10.1.1.23

---10.1.1.24

|---leaders

----shard1              //当前shard的leader节点

---10.1.1.21

-----shard2

----10.1.1.24

/observer                //负责watch collections中节点的变化,

由leader节点更新 clusterstate.json节点的内容,observer节点需要在系统初始 化过程中最新选举出leader节点,做watch collections下的 节点的变化。

|---election          //其下是供选择的节点

|----leader           //这样一个好处是每个client节点无需对多个zookeeper的节点监控计算,由单独的节点对这些变化的节点做监控, 来更新集群状态,这样每个client只需要 watch 集群状态 内容zookeeper节点即可。

/live_nodes

|---10.1.1.21

|----10.1.1.22

|----10.1.1.23

|-----10.1.1.24

/clusterstate.json                      //集群状态,当有节点变化时,更新这个节点 内容,每个client端监听该节点内容的变化, 缓存在本地cache中。

相关内容如下:

{collection1={

"shards":{

"shard1":{

"range":"80000000-ffffffff",

“leader”:node1,

"replicas":{

"node1":{

"state":"alive",         "node_name":"192.168.1.21:8983"},

"node2":{

"state":"alive",

"node_name":"192.168.1.22:8983"

}}},

"shard2":{

"range":"0-7fffffff",

"state":"active",

“leader”:node3,

"replicas":{

"node3":{

"node_name":"192.168.1.23:8983"},

"core_node4":{

"node_name":"192.168.1.24:8983"

}}},

模块设计说明

1. 数据切分、节点扩容、key hash

对于数据切分,数据的范围取Integer.MIN_VALUE, Integer.MAX_VALUE,首次初始化时,根据规划的Shard的数量,平均进行切分,每个Shard负责一个固定的数据范围,比如Shard1[0-7fffffff],这些Shard和数据的范围会持久化到zookeeper节点上,以便于集群重启后,从zookeeper本地拉起Shard划分和数据范围的相关数据,如下图所示。

/collections

|----collection1

|----leader_elect

----shard1[0-7ffffffff]

----shard2[800000-9ffffffff]

当需要扩容缓存节点时,管理员可以对Shard进行split操作,生成两个新的Shard,每个Shard负责一部分数据,注册在zooleeper上的/collections/collection1/leader_elect节点下。比如Shard1[0-7ffffffff]经过split操作后,变成Shard1_1[0-3ffffffff]和Shard1_2[400000-7fffffffff]。

/collections

|----collection1

|----leader_elect

----shard1[0-7ffffffff]

----shard2[800000-9ffffffff]

----shard1_1[0-3ffffffff]

----shard1_2[0-3ffffffff]

新的节点加入到新的Shard分区中,完成leader选举等一系列操作后,更新集群拓扑状态,并删除老的Shard分区,这样新的Shard就处于可用状态。

对于key的hash定位,采用murmurhash3_x86_32 算法,效率比较高,然后判断该hash值落在哪个shard的数据范围内,进行数据的分区定位。

2. 缓存代理Agent

Agent作为缓存节点的代理,一方面和zookeeper进行通信,把缓存节点的状态通知给zookeeper,另外一方面对redis缓存节点做管理和监控。

1) Agent检测redis节点是否存活:

需要在Agent中调用以下脚本(monitor_redis.sh),把返回的结果,通知给zookeeper

ALIVE=$(/opt/cache/redis-2.6.16/src/redis-cli -h 10.1.1.25 -p 6379 -a 123 PING)

echo $ALIVE

2) 变更为master节点

当节点上的agent在zookeeper上成为leader节点时,需要通知agent把它代理的redis变更为master节点,agent调用以下脚本。

主节点的脚本(redis_master.sh):

#!/bin/bash

/opt/cache/redis-2.6.16/src/redis-cli -h 10.1.1.26 -p 6379 slaveof NO ONE

3) 变更为slave节点

当节点上的agent在zookeeper上成为replica节点时,需要通知agent把它代理的redis变更为slave节点,agent调用以下脚本。

slave节点脚本(redis_slaves.sh):

#!/bin/bash

/opt/cache/redis-2.6.16/src/redis-cli -h 10.1.1.26 -p 6379 slaveof 10.1.1.25 6379

3. 集群状态观察者Observer

Observer负责对整个集群collection下的Shard节点的变动进行监听,更新zookeeper上的集群状态节点cloudstate.json。

Agent节点在启动过程中,首选要做的就是Observer的选举。

Observer需要由zookeeper选举出来后,监听collections下节点的变化,若有变化则进行处理process,计算的结果设置到zookeeper的cloudstate.json节点。

当cloudstate.json节点数据变化时,负责监听该节点的所有客户端都更新本地客户端内存。

/observer

|---election

----10.1.1.21

----10.1.1.22

-----10.1.1.23

|----leader

-----10.1.1.22

4. Shard leader选举

Shard节点在zookeeper上创建完成后,缓存节点在启动的过程中,需要通过命令行-D参数或者配置文件的形式加入到集群中的某一个Shard分区下,参与leader的选举,具体实现是为每个节点生成一个数字,每个节点只需要监控比自己小的节点即可,如有变化,则进行通知,并使得数字最小的节点成为leader节点。

/collections

|----collection1

|----leader_elect

----shard1               //节点启动时,一共需要分几个分区,需要 声明该节点属于哪个shard

---eclection         //参与选举的节点列表,竞争成为leader节   点,并更新leaders节点列表和clusterstate.json节点内容,并调用脚 本 更改redis的master slave配置

----10.1.1.21

----10.1.1.22

----shard2

---eclection

---10.1.1.23

---10.1.1.24

|---leaders

----shard1              //当前shard的leader节点

---10.1.1.21

-----shard2

----10.1.1.24

5. 缓存节点的扩容

当某shard的访问压力过大或者数据量比较大时候,节点的扩展有两种方式,

一种是增加shard中的节点数量,提高读的能力,这种方式已经实现;

另外一种方式对压力大的shard做split的操作,一个shard分割为两个shard,提高shard的写数据的能力,这种节点的扩展方式目前还不支持,已纳入到后续的计划中。

使用说明

Agent的启动脚本:

MAIN="com.newcosoft.cache.agent.AgentMain"
$JAVA $JAVA_OPTS  -cp "$CLASSPATH" $JVMFLAGS $MAIN  -Dcol=col1 -Dshard=shard1 -Dnode=node25 \
  -DbaseUrl=10.1.1.25:6379 -DscriptPath=/opt/lsmp -DshardNum=3 -Dzk_url=10.1.1.25:2181

其中-Dcol表示当前创建的collection名称,对于redis来讲,代表要存储库的逻辑名称

-Dshard表示当前的节点的shard名称

-Dnode表示当前节点的逻辑名称

-DbaseUrl表示redis的主机IP和端口号

-DscriptPath表示redis监控和操作相关的脚本的路径,脚本有monitor_redis.sh、redis_master.sh、redis_slaves.sh

-DshardNum表示当前collection中的shard数目

-Dzk_url代表zookeeper集群的地址

Client端的使用:

在使用disgear的client端启动初始化中,引用disgear相关的jar,并调用

com.newcosoft.client.ClusterStateCacheManager.INSTANCE=new ClusterStateCacheManager(zkUrl);

ClusterStateCacheManager.INSTANCE.createClusterStateWatcher();

创建clusterState的监听器。

这样后续通过com.newcosoft.client.ClusterStateCacheManager.INSTANCE.getClusterState()就可以获得当前集群的节点状态,

进而选择合适的节点进行分发数据存取请求。

基于redis的分布式缓存disgear开源到github上了的更多相关文章

  1. 基于Redis的分布式锁到底安全吗(上)?

    基于Redis的分布式锁到底安全吗(上)?  2017-02-11 网上有关Redis分布式锁的文章可谓多如牛毛了,不信的话你可以拿关键词“Redis 分布式锁”随便到哪个搜索引擎上去搜索一下就知道了 ...

  2. 基于redis的分布式锁

    <?php /** * 基于redis的分布式锁 * * 参考开源代码: * http://nleach.com/post/31299575840/redis-mutex-in-php * * ...

  3. 基于Redis的分布式锁到底安全吗(下)?

    2017-02-24 自从我写完这个话题的上半部分之后,就感觉头脑中出现了许多细小的声音,久久挥之不去.它们就像是在为了一些鸡毛蒜皮的小事而相互争吵个不停.的确,有关分布式的话题就是这样,琐碎异常,而 ...

  4. 基于Redis的分布式锁安全性分析-转

    基于Redis的分布式锁到底安全吗(上)?  2017-02-11 网上有关Redis分布式锁的文章可谓多如牛毛了,不信的话你可以拿关键词“Redis 分布式锁”随便到哪个搜索引擎上去搜索一下就知道了 ...

  5. 基于Redis的分布式锁和Redlock算法

    1 前言 前面写了4篇Redis底层实现和工程架构相关文章,感兴趣的读者可以回顾一下: Redis面试热点之底层实现篇-1 Redis面试热点之底层实现篇-2 Redis面试热点之工程架构篇-1 Re ...

  6. 身为一枚优秀的程序员必备的基于Redis的分布式锁和Redlock算法

    1 前言 今天开始来和大家一起学习一下Redis实际应用篇,会写几个Redis的常见应用. 在我看来Redis最为典型的应用就是作为分布式缓存系统,其他的一些应用本质上并不是杀手锏功能,是基于Redi ...

  7. Redis-基本概念、java操作redis、springboot整合redis,分布式缓存,分布式session管理等

    NoSQL的引言 Redis数据库相关指令 Redis持久化相关机制 SpringBoot操作Redis Redis分布式缓存实现 Resis中主从复制架构和哨兵机制 Redis集群搭建 Redis实 ...

  8. 基于 redis 的分布式锁实现 Distributed locks with Redis debug 排查错误

    小结: 1. 锁的实现方式,按照应用的实现架构,可能会有以下几种类型: 如果处理程序是单进程多线程的,在 python下,就可以使用 threading 模块的 Lock 对象来限制对共享变量的同步访 ...

  9. Spring+Shiro搭建基于Redis的分布式权限系统(有实例)

    摘要: 简单介绍使用Spring+Shiro搭建基于Redis的分布式权限系统. 这篇主要介绍Shiro如何与redis结合搭建分布式权限系统,至于如何使用和配置Shiro就不多说了.完整实例下载地址 ...

随机推荐

  1. Orchard运用 - 为评论启用Gravatar头像

    在前一篇随笔中我曾分享如何为Orchard特定主题添加独立代码文件, 今儿延续如何把对应代码应用到Views上. 对此我不妨把为评论启用Gravatar头像这一例子来实现.其实很简单, 思路大概就是创 ...

  2. vmwareubuntu18.04网络配置

    用vm安装ubuntu的时候要如果使用的是net模式,要确保vm的net服务和dhcp服务开启了,右键我的电脑-管理-服务和应用程序-服务找到对应的vm net服务和dhcp服务启动.

  3. IE系列不支持圆角等CSS3属性的解决方案

    IE系列浏览器不支持CSS的圆角(border-radius)等CSS3属性是一个众所周知的问题,而FF.Chrome原生的浏览器支持是的优雅的圆角感觉较好,如何解决这个问题呢? 一种比较传统的方案是 ...

  4. JavaScript中的单引号和双引号解决

    在使用JavaScript显示消息或者传递字符数据的时候,经常会碰到数据中夹杂单引号(')或者双引号("),这种语句往往会造成JavaScript报错.对此一般采用/'或者/"的解 ...

  5. ECharts学习总结(三):ECharts图表对象的初始化(init)详解以及注意事项

    一.相关js文件的引入 这里我们采用标签式引入文件的方式,我们引入两个js文件,一个是esl.js文件和一个echarts.js. <script src="js/esl.js&quo ...

  6. JS辨别访问浏览器

    项目中需要扫描二维码之后自动分辨出是android还是ios系统,针对于不同的系统进行不同的下载. <script type="text/javascript"> /* ...

  7. Android4.2.2 Gallery2源码分析(2)——发现Gallery.java

    上文中,main.xml是我直接提出来的,并没有说明是怎么找到它的,现在说明发现它的理由: 一般我们分析界面布局会用到hierarchyviewer这个工具,从工具中,我们对应到视图,最主要的视图id ...

  8. 免费的多数据库管理工具sqldbx个人版本

    SqlDbx是一个先进的Sql编辑器和数据库对象资源管理器SqlDbx仅一个可执行的文件不需要安装 SqlDbx与SSMS对象内存占差的不是一点点,但功能与SSMS相当 优点:支持多数据库,占用内存小 ...

  9. Word TOC域的使用说明

    TOC域的使用说明: 域代码:TOC(目录)域 { TOC [Switches ] } 建立一个目录.TOC 域根据标题级别.指定样式或由 TC(目录项)域指定的项目来收集目录项.在使用“插入”菜单中 ...

  10. const 与过载

    1.方法包括方法名,返回类型,形参表,修饰符. 2.对于一个方法,const可以出现的地方有返回类型,形参表,和方法后(const成员方法). 3.返回类型的常量性(是否为const)不同,不能构成过 ...