Dynomite 使用教程
Dynomite 简介
Dynomite是NetFlix对亚马逊分布式引擎Dynamo的一个开源通用实现,它不仅支持基于内存K/V数据库,
还支持持久化的MySQL、BerkeleyDb、LevelDb等数据库,并具有简单、高效、支持跨数据中心的数据复制功能等优点。
Dynomite的最终目标是提供数据库存储引擎不能提供的简单、高效、跨数据中心的数据复制功能。目前,Dynomite已经实现了对Redis和Memcached的支持。
Dynomite 安装配置
Build
从源代码构建Dynomite并启用调试日志,禁用assertions:
$ git clone git@github.com:Netflix/dynomite.git
$ cd dynomite
$ autoreconf -fvi
$ ./configure --enable-debug=yes // 开发环境需要,生产环境不需要
$ make
$ src/dynomite -h
调试模式构建Dynomite:
$ git clone git@github.com:Netflix/dynomite.git
$ cd dynomite
$ autoreconf -fvi
$ CFLAGS="-ggdb3 -O0" ./configure --enable-debug=full
$ make
$ sudo make install
Help
Usage: dynomite [-?hVdDt] [-v verbosity level] [-o output file]
[-c conf file] [-s stats port] [-a stats addr]
[-i stats interval] [-p pid file]
Options:
-h, --help : this help
-V, --version : show version and exit
-t, --test-conf : test configuration for syntax errors and exit
-g, --gossip : enable gossip (default: disabled)
-d, --daemonize : run as a daemon
-D, --describe-stats : print stats description and exit
-v, --verbosity=N : set logging level (default: 5, min: 0, max: 11)
-o, --output=S : set logging file (default: stderr)
-c, --conf-file=S : set configuration file (default: conf/dynomite.yml)
-p, --pid-file=S : set pid file (default: off)
-x, --admin-operation=N : set size of admin operation (default: 0)
Configuration
Dynomite可以通过进程启动时通过-c或--conf-file命令行参数指定的YAML文件进行配置。 配置文件可解析并理解以下关键字:
- env 指定节点的环境。 目前支持aws和网络(用于物理数据中心)。
- datacenter 数据中心的名称。 请参考架构文档。
- rack 机架的名称。 请参考架构文档.
- dyn_listen dynomite节点用于进行内部通信和gossip的端口。
- enable_gossip 启用gossip而不是静态tokens(默认值:false)。gossip是实验性的。
- gos_interval 在gossip round结束时的睡眠时间(以毫秒为单位)。
- tokens 节点拥有的令牌。目前,我们不支持vnode,所以现在只能使用一个令牌。
- dyn_seed_provider 提供seed节点列表的seed提供者实现。
- dyn_seeds seed节点列表,格式如下:address:port:rack:dc:tokens(目前不支持vnode的节点)。
- listen 该服务器池的监听地址和端口(名称:port或ip:port)
- timeout 我们等待与服务器建立连接或从服务器接收响应的以msec为单位的超时值。默认情况下,我们无限期地等待。
- preconnect 一个布尔值,用于控制dynomite是否应在进程启动时预先连接到此池中的所有服务器。默认为false。
- data_store一个整数值,用于控制服务器池是否使用redis(0)或memcached(1)或其他协议。默认为redis(0)。
- auto_eject_hosts 一个布尔值,用于控制在连续失败server_failure_limit次时是否应暂时弹出该服务器。默认为false。
- server_retry_timeout 当auto_eject_host设置为true时,在临时弹出的服务器上重试之前等待的超时值(以毫秒为单位)。 默认为30000毫秒。
- server_failure_limit 服务器上连续发生故障的次数,当auto_eject_host设置为true时,达到该次数会导致临时弹出。默认为2。
- servers 服务器池的本地服务地址,端口和权重的列表(名称:port:weight或ip:port:weight)。目前只有一个。
- secure_server_option 加密通信。 必须是“none”,“rack”,“datacenter”或“all”之一。 datacenter意味着数据中心之间的所有通信都是加密的,但在datacenter内则不是。
rack
表示机架和区域之间的所有通信都已加密,但同一机架内节点之间的通信未加密。all
意味着所有节点之间的所有通信都被加密。 而none
表示没有任何通信被加密。 - stats_listen REST端点的地址和端口号以及访问统计信息。
- stats_interval 以msec为单位设置统计间隔(默认值:30000毫秒)。
- mbuf_size mbuf块的大小(以字节为单位)(默认值:16384字节)。
- max_msgs 要分配的最大消息数(默认值:200000)。
可参考官方配置文件示例.
最后,为了更容易地编写语法正确的配置文件,dynomite提供了一个命令行参数-t或--test-conf,可用于测试YAML配置文件是否存在任何语法错误。
Dyno客户端
Dyno客户端特征
- 永久连接的连接池 - 这有助于减少客户端连接重用时Dynomite服务器上的连接流失。
- 支持拓扑的负载平衡(令牌感知),用于避免向不是指定数据所有者的Dynomite协调节点跳转。
- 当本地Dynomite机架节点发生故障时,通过智能故障切换到远程机架实现应用程序弹性。
- 通过不断监控连接健康状况并回收不健康的连接,应对弹回的网络故障。
- 通过surgically将流量从任何需要离线维护的节点路由出去的能力。
- 灵活的重试策略,如指数退避等。
- 洞察连接池指标。
- 高度可配置和可插拔的连接池组件,用于实现您的高级功能。
maven依赖
可直接将下面的maven依赖代码拷贝到pom.xml文件中。
<!-- dyno客户端核心包 -->
<dependency>
<groupId>com.netflix.dyno</groupId>
<artifactId>dyno-core</artifactId>
<version>1.6.3</version>
</dependency>
<!-- dyno客户端整合jedis的包 -->
<dependency>
<groupId>com.netflix.dyno</groupId>
<artifactId>dyno-jedis</artifactId>
<version>1.6.3</version>
</dependency>
示例代码
package com.linuxcoming.dyno;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import com.netflix.dyno.connectionpool.Host;
import com.netflix.dyno.connectionpool.Host.Status;
import com.netflix.dyno.connectionpool.HostSupplier;
import com.netflix.dyno.connectionpool.OperationResult;
import com.netflix.dyno.connectionpool.TokenMapSupplier;
import com.netflix.dyno.connectionpool.impl.lb.HostToken;
import com.netflix.dyno.jedis.DynoJedisClient;
public class DynoDemo {
protected DynoJedisClient client;
protected final String rack;
protected final String clusterName;
public DynoDemo(String clusterName,String localRack){
this.rack = localRack;
this.clusterName = clusterName;
}
public void initWithHost(){
//Dynomite监听端口
final int port = 8102;
//配置主机
final HostSupplier localHostSupplier = new HostSupplier(){
final Host hostSupplierHost = new Host("localhost",port,rack,Status.Up);
public List<Host> getHosts() {
return Collections.singletonList(hostSupplierHost);
}
};
//自定义TokenMapSupplier,关联token与host
final TokenMapSupplier tokenSupplier = new TokenMapSupplier(){
final Host tokenHost = new Host("localhost",port,rack,Status.Up);
final HostToken localHostToken = new HostToken(100000l,tokenHost);
public List<HostToken> getTokens(Set<Host> activeHosts) {
return Collections.singletonList(localHostToken);
}
public HostToken getTokenForHost(Host host, Set<Host> activeHosts) {
return localHostToken;
}
};
init(localHostSupplier,port,tokenSupplier);
}
public void init(HostSupplier hostSupplier,int port,final TokenMapSupplier tokenSupplier){
client = new DynoJedisClient.Builder().withApplicationName("demo")
.withHostSupplier(hostSupplier).withTokenMapSupplier(tokenSupplier).build();
}
public void runSimpleTest(){
int numKeys = 10;
System.out.println("Simple test");
for(int i=0;i<numKeys;i++){
System.out.println("writing key/value=>DynoClientTest:"+i+" / "+i);
client.set("DynoClientTest-"+i,""+i);
}
for(int i=0;i<numKeys;i++){
OperationResult<String> result = client.d_get("DynoClientTest-"+i);
System.out.println("Reading key: "+i+",value:"+result.getResult());
}
client.stopClient();
}
public static void main(String[] args){
DynoDemo demo = new DynoDemo("clustTest","rack1");
demo.initWithHost();
demo.runSimpleTest();
}
}
运行结果
Simple test
writing key/value=>DynoClientTest:0 / 0
writing key/value=>DynoClientTest:1 / 1
writing key/value=>DynoClientTest:2 / 2
writing key/value=>DynoClientTest:3 / 3
writing key/value=>DynoClientTest:4 / 4
writing key/value=>DynoClientTest:5 / 5
writing key/value=>DynoClientTest:6 / 6
writing key/value=>DynoClientTest:7 / 7
writing key/value=>DynoClientTest:8 / 8
writing key/value=>DynoClientTest:9 / 9
Reading key: 0,value:0
Reading key: 1,value:1
Reading key: 2,value:2
Reading key: 3,value:3
Reading key: 4,value:4
Reading key: 5,value:5
Reading key: 6,value:6
Reading key: 7,value:7
Reading key: 8,value:8
Reading key: 9,value:9