dynomite原理简介
有问题欢迎讨论
项目地址:
https://github.com/Netflix/dynomite
文档地址:
https://github.com/Netflix/dynomite/wiki
redis命令支持情况:
https://github.com/Netflix/dynomite/blob/dev/notes/redis.md
下载地址:
https://github.com/Netflix/dynomite/releases
dynomite使用netflix开源的一个开源将非分布式的缓存系统改造成分布式的缓存系统,根据亚马逊的Dynamo进行设计,是一个高可用,高性能,支持跨数据中副本的分布式存储代理层。
上面是官方给的两个拓扑图,其结构和elasticsearch集群的结构比较相似。 这个图里面有两个概念,datacent和rack。这两个概念举例来理解,假设我们在阿里云有集群,在腾讯云也有集群,这就叫两个datacent,或者换种说法,假设有很多集群,这些集群可以根据物理机所在位置或者其他标准,分成了两大部分,这就叫两个datacent。 然后在每个datacent内,可能某些物理机在一个机房或者机架甚至就是一个机器上的几个虚拟机,那么这些机器之间的通信等速度肯定会更快,这些机器可以组成一个集群,就叫一个rack。在dynomite拓扑结构中,每个rack都是一个完整集群,每个rack的都拥有完整的数据,多个rack间相互备份,这就达到了高可用,具体同步机制后面讲。
dynomite结构中,每个rack都是一个一致性hash环,具体规则是rack上每个节点都是个redis master,是可读写的。在每个redis节点上都挂载着一个dynomite代理,每个代理持有一个tokens,一致性hash的分配就是根据这个tokens来的,tokens计算规则:从0开始 token = (4294967295 / numberOfNodesInRack) * nodeIndex。每个rack上存在节点都是可以不同的,不需要对应,因为每个rack上的tokens都是重新计算的。
当客户端的请求到达任意一个dynomite代理后,dynomite会根据tokens计算出这个key是否属于自己管理的节点,如果不是的话,会把请求发送到对应的dynomite代理上。
同时,还会把这个请求发送到其他的rack的dynomite代理上,以此来完成rack间的数据同步,这个rack间的数据同步时异步的,但是当我们要求强一致性的时候,可以通过配置参数,当有多少个rack完成数据写入时,才返回结果,根据对一致性要求程度的不同来设置不同的参数。相关参数:
# DC_ONE 本节点读写入完成及请求完成,其他的rack异步写入
# DC_QUORUM 同步写入到指定个数的rack中,其他的节点异步写入
# DC_SAFE_QUORUM 和DC_QUORUM类似,不过这个参数读写都要在指定个数的rack中成功并且数据校验同步,才算请求成功,不然会报错。
# yaml配置参数
read_consistency: dc_quorum
write_consistency: dc_quorum
PS:dynomite提供的有自己的客户端,可以在本地缓存tokens信息,直接客户端计算对应的dynomite节点地址,不用服务端去计算,提高了响应速度。
参考:https://github.com/richieyan/IntroDynomitedb
简单的异地多活高可用方案:
- 1、两地各键一个datacent
- 2、每个datacent中建立两个rack
- 3、每个rack上的redis-server为一个sentinel集群,dynomite高可用通过一个redis上挂载多个dynomite实现
- 4、sentinel集群通过client-reconf-script脚本,在master节点发生switch操作时,自动去修改dynomite代理地址指向的redis server地址
dynomite安装使用
安装:
# 下载release版本后,解压,然后进入目录
yum install autoconf automake libtool libffi-dev
autoreconf -fvi
make
# make后src目录下的dynomite为可执行文件
src/dynomite -h
# 直接复制到用户目录方便使用
mkdir -p ~/dynomite/bin
# rsa的默认存储位置 在里面生成dynomite.pem和recon_key.pem
mkdir -p ~/dynomite/conf
# 自定义log路径
mkdir -p ~/dynomite/logs
cp src/dynomite ~/dynomite/bin
配置使用:
首先,启动三个redis,port分别为5000,5001,5002
每个redis-server节点上需要挂在一个dynomite代理
dynomite配置文件(我的yml文件放在conf目录下):
node1.yml
dyn_o_mite:
# 数据中心
datacenter: dc1
# 集群分区
rack: rack1
# dynomite之间的内部通讯端口
dyn_listen: 127.0.0.1:8101
# 其他的dynomite节点 ip:port:rack:datacenter:tokens
dyn_seeds:
- 127.0.0.1:8201:rack1:dc1:1431655765
- 127.0.0.1:8301:rack1:dc1:2863311530
# 存储类型 0 代表redis 1 代表memcached
data_store: 0
# 外部访问的端口
listen: 127.0.0.1:8102
dyn_seed_provider: simple_provider
# 代理的redis server节点 ip:port:weight
# servers应该是可以配置多个的,但是文档说目前只能配一个,根据weight猜测,这里可能是给单节点高可用预留的
servers:
- 127.0.0.1:5000:1
# 集群标识 计算公式 从0开始 token = (4294967295 / numberOfNodesInRack) * nodeIndex
tokens: 0
# 状态监听端口
stats_listen: 127.0.0.1:30000
# rsa密匙 生成命令 ssh-keygen -t rsa -f ~/dynomite/conf/dynomite.pem
pem_key_file: conf/dynomite.pem
# 生成方法如上
recon_key_file: conf/recon_key.pem
recon_iv_file: conf/recon_iv.pem
node2.yml
dyn_o_mite:
# 数据中心
datacenter: dc1
# 集群分区
rack: rack1
# dynomite之间的内部通讯端口
dyn_listen: 127.0.0.1:8201
# 其他的dynomite节点 ip:port:rack:datacenter:tokens
dyn_seeds:
- 127.0.0.1:8101:rack1:dc1:0
- 127.0.0.1:8301:rack1:dc1:2863311530
# 存储类型 0 代表redis 1 代表memcached
data_store: 0
# 外部访问的端口
listen: 127.0.0.1:8202
dyn_seed_provider: simple_provider
# 代理的redis server节点 ip:port:weight
# servers应该是可以配置多个的,但是文档说目前只能配一个,根据weight猜测,这里可能是给单节点高可用预留的
servers:
- 127.0.0.1:5001:1
# 集群标识 计算公式 从0开始 token = (4294967295 / numberOfNodesInRack) * nodeIndex
tokens: 1431655765
# 状态监听端口
stats_listen: 127.0.0.1:30001
# rsa密匙 生成命令 ssh-keygen -t rsa -f # rsa密匙 生成命令 ssh-keygen -t rsa -f ~/dynomite/conf/dynomite.pem
pem_key_file: conf/dynomite.pem
# 生成方法如上
recon_key_file: conf/recon_key.pem
recon_iv_file: conf/recon_iv.pem
node3.yml
dyn_o_mite:
# 数据中心
datacenter: dc1
# 集群分区
rack: rack1
# dynomite之间的内部通讯端口
dyn_listen: 127.0.0.1:8301
# 其他的dynomite节点 ip:port:rack:datacenter:tokens
dyn_seeds:
- 127.0.0.1:8101:rack1:dc1:0
- 127.0.0.1:8201:rack1:dc1:1431655765
# 存储类型 0 代表redis 1 代表memcached
data_store: 0
# 外部访问的端口
listen: 127.0.0.1:8302
dyn_seed_provider: simple_provider
# 代理的redis server节点 ip:port:weight
# servers应该是可以配置多个的,但是文档说目前只能配一个,根据weight猜测,这里可能是给单节点高可用预留的
servers:
- 127.0.0.1:5002:1
# 集群标识 计算公式 从0开始 token = (4294967295 / numberOfNodesInRack) * nodeIndex
tokens: 2863311530
# 状态监听端口
stats_listen: 127.0.0.1:30002
# rsa密匙 生成命令 ssh-keygen -t rsa -f ~/dynomite/conf/dynomite.pem
pem_key_file: conf/dynomite.pem
# 生成方法如上
recon_key_file: conf/recon_key.pem
recon_iv_file: conf/recon_iv.pem
遇到的错误:
load_private_rsa_key_by_file:48 Error: file conf/dynomite.pem does not exist
entropy_key_iv_load:368 Error: file conf/recon_key.pem does not exist
entropy_key_iv_load:372 Error: file conf/recon_iv.pem does not exist
解决方案:
# yaml文件增加两个配置项
# rsa密匙 生成命令 ssh-keygen -t rsa -f ~/dynomite/conf/dynomite.pem
pem_key_file: conf/dynomite.pem
# 生成方法如上
recon_key_file: conf/recon_key.pem
recon_iv_file: conf/recon_iv.pem
启动dynomite:
bin/dynomite -c conf/node1.yml -d --output=logs/node1.log
bin/dynomite -c conf/node2.yml -d --output=logs/node2.log
bin/dynomite -c conf/node3.yml -d --output=logs/node3.log
测试:
# 和普通redis客户端一样的访问方式 把端口换成dynomite对外的端口即可
redis-cli -h 127.0.0.1 -p 8102
127.0.0.1:8202> set test1 1
OK
127.0.0.1:8202> set test2 1
OK
127.0.0.1:8202> set test3 1
OK
127.0.0.1:8202>
然后直接连接redis查看数据,会发现每个redis节点中有一条数据。