时间戳服务器:XiaoMi Chronos

jopen 10年前

Chronos,在古希腊语意为时间,是小米公司开发的实现高可用高性能提供全局唯一而且严格单调递增timestamp的服务。

Chronos 采用主备架构,主服务器挂了以后备服务器迅速感知并接替服务,从而实现系统的高可用。服务端使用Thrift框 架,经测试每秒可处理约60万次RPC请求,客户端单线程每秒可请求6万次(本地服务器),保证高性能与低延时。全局只有唯一的 ChronosServer提供服务,分配的timestamp保证严格单调递增,并且将已分配的值持久化到ZooKeeper上,即使发生 failover也能保证服务的正确性。

原理

时间戳服务器:XiaoMi Chronos

Chronos依赖ZooKeeper实现与HBase类 似的Leader Election机制,ChronosServer启动时将自己的信息写到ZooKeeper的Master临时节点上,如果主服务器已经存在,那么就记 录到BackupServers节点上。一旦Master临时节点消失(主服务器发生failover),所有备服务器收到ZooKeeper通知后参与 新一轮的选主,保证最终只有一个新的主服务器接替服务。

ChronosServer运行时会启动一个Thrift服务器,提供getTimestamp()和getTimestamps(int)接口, 并且保证每次返回的timestamp都是严格单调递增的。返回的timestamp与现实时间有基本对应关系,为当前Unix time乘以2的18次方(足够使用1115年),由于我们优化了性能,所以如果存在failover就不能保证这种对应关系的可靠性

ChronosClient启动时,通过访问ZooKeeper获得当前的主ChronosServer地址,连接该服务器后就可以发送 Thrift RPC请求了。一旦主服务器发生failover,客户端请求失败,它会自动到ZooKeeper获得新的主ChronosServer地址重新建立连 接。

使用

Chronos服务端

  1. 进入chronos-server目录,通过mvn clean package -DskipTests编译源码。
  2. 进入target里面的conf目录,编辑chronos.conf,填写依赖的ZooKeeper配置。
  3. 进入target里面的bin目录,执行sh ./chronos.sh既可运行ChronosServer。

Chronos客户端

  1. 进入chronos-client目录,通过mvn clean package -DskipTests编译源码。
  2. 客户端在pom.xml添加chronos-client的依赖(请使用对应的Thrift版本)。

     <dependency>     <groupId>com.xiaomi.infra</groupId>     <artifactId>chronos-client</artifactId>     <version>1.2.0-thrift0.5.0</version>   </dependency>
  3. 创建ChronosClient对象,如new ChronosClient("127.0.0.1:2181", "default-cluster")

  4. 发送RPC请求,如chronosClient.getTimestamp()chronosClient.getTimestamps(10)

快速体验

  1. 参考ZooKeeper文档,编译ZooKeeper并运行在127.0.0.1:2181上。
  2. 获得chronos源代码,执行mvn clean packge -DskipTests编译(需要安装Thrift)。
  3. 进入chronos-server的bin目录,执行sh ./chronos.sh运行ChronosServer。
  4. 进入chronos-client目录,执行mvn exec:java -Dexec.mainClass="com.xiaomi.infra.chronos.client.ChronosClient" -Dexec.args="127.0.0.1:2181 default-cluster"

场景

  • 提供全局严格单调递增的timestamp,用于实现Percolator等全局性事务。
  • 提供全局唯一的值,相比snowflake不依赖NTP服务,并且提供failover机制。

工具

  • 提供list_servers.rb脚本,可监控当前的所有运行的ChronosServer状态。
  • 提供translate_timestamp.rb脚本,可将timestamp转化为可读的世界时间。
  • 提供process_benchmark_log.rb脚本,可处理Benchmark程序产生的日志。

测试

  • 性能测试
客户端线程数 平均QPS 平均Latency(毫秒) 平均Failover时间(秒) 服务端总QPS
1 10792.757 0.093 3.056 32378.271
10 7919.679 0.127 3.053 237590.370
20 6676.801 0.164 3.952 400788.060
50 3954.026 0.255 4.044 593103.900
100 1791.251 0.605 5.470 537375.300
50(最优) 3993.749 0.251 0.000 599062.350
  • Failover测试

持续杀掉ChronosServer和ZooKeeper进程没有发现正确性问题,failover时间符合预期。

注意,Failover时间可通过ZooKeeper的tickTime和Chronos的sessionTimeout来设置线上部署时应配合Supervisor或者God来监控和拉起服务


 

项目主页:http://www.open-open.com/lib/view/home/1403854604952