首页 > 编程语言 >java-raft框架之atomix进行分布式管理

java-raft框架之atomix进行分布式管理

时间:2023-05-19 10:32:50浏览次数:56  
标签:127.0 java 0.1 atomix io import raft id


共识算法

在一个分布式的系统中,管理各个节点的一致性(共识)一直是个很有难度的问题。

在近几十年的发展中,于1990年诞生的Paxos算法是其中最为经典的代表,并一统江湖数几十载。

如著名的zookeeper、chubby都是基于Paxos算法的经典应用。


不过Paxos算法的复杂度和难以理解性,也吸引了一些大佬想让它变得更加简单。

为此,以简单和易理解为目标的Raft算法便于2014年横空出世。

其Raft论文地址为:https://web.stanford.edu/~ouster/cgi-bin/papers/raft-atc14

为了快速了解,也通过结合https://raft.github.io/中的动画演示快速了解。

尽管Raft算法的发布时间较短,不过它的具体落地方面可谓是百花齐放,如K8S中的etcd就是使用raft算法实现的代表应用。


atomix框架

atomix是一个基于raft算法,使用java语言进行实现的一个分布式框架,可以运用在各种分布式场景中。

更多关于atomix的相关介绍,可以在对应的github中找到:https://github.com/atomix/atomix-archive

需要注意的是:基于java的atomix现已停止维护,这里仅用作学习目的,在分布式系统中体验一下。


本文选用的atomix版本为最新的3.1.12版本。https://github.com/atomix/atomix-archive/releases/tag/atomix-3.1.12

所对应的maven依赖为:

<atomix.version>3.1.12</atomix.version>
	
	<dependency>
		<groupId>io.atomix</groupId>
		<artifactId>atomix</artifactId>
		<version>${atomix.version}</version>
	</dependency>
	<dependency>
		<groupId>io.atomix</groupId>
		<artifactId>atomix-raft</artifactId>
		<version>${atomix.version}</version>
	</dependency>

下面以在分布式系统中的常见场景,来快速掌握下atomix的用法

数据存储

使用atomix进行数据存储与查询

package io.github.puhaiyang;

import io.atomix.cluster.ClusterMembershipService;
import io.atomix.cluster.Member;
import io.atomix.cluster.discovery.BootstrapDiscoveryProvider;
import io.atomix.core.Atomix;
import io.atomix.core.election.AsyncLeaderElector;
import io.atomix.core.map.AsyncAtomicMap;
import io.atomix.primitive.Recovery;
import io.atomix.protocols.raft.MultiRaftProtocol;
import io.atomix.protocols.raft.partition.RaftPartitionGroup;
import io.atomix.utils.time.Versioned;

import java.io.File;
import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;

public class ClusterTest {
    private static String LOCAL_DATA_DIR = "db/partitions/";
    private static String groupName = "raft";
    private static Integer MAX_RETRIES = 5;

    public static void main(String[] args) throws Exception {
        Atomix atomix = buildAtomix();
        //atomix启动并加入集群
        atomix.start().join();

        //创建atomixMap
        AsyncAtomicMap<Object, Object> asyncAtomicMap = atomix.atomicMapBuilder("myCfgName")
                .withProtocol(MultiRaftProtocol.builder(groupName)
                        .withRecoveryStrategy(Recovery.RECOVER)
                        .withMaxRetries(MAX_RETRIES)
                        .build())
                .withReadOnly(false)
                .build()
                .async();
        //进行数据存储
        asyncAtomicMap.put("myBlog", 
        //进行查询
        CompletableFuture<Versioned<Object>> myBlog = asyncAtomicMap.get("myBlog");
        Versioned<Object> objectVersioned = myBlog.get();
        System.out.printf("value:%s version:%s%n", objectVersioned.value(), objectVersioned.version());
    }

    private static Atomix buildAtomix() {
        List<String> raftMembers = Collections.singletonList("node1");
        //创建atomix
        return Atomix.builder(ClusterTest.class.getClassLoader())
                .withClusterId("my-cluster")
                .withMemberId("node1")
                .withHost("127.0.0.1")
                .withPort(6789)
                .withMembershipProvider(BootstrapDiscoveryProvider.builder().build())
                .withManagementGroup(RaftPartitionGroup.builder("system")
                        .withNumPartitions(1)
                        .withDataDirectory(new File(LOCAL_DATA_DIR, "system"))
                        .withMembers(raftMembers)
                        .build())
                .addPartitionGroup(RaftPartitionGroup.builder(groupName)
                        .withNumPartitions(raftMembers.size())
                        .withDataDirectory(new File(LOCAL_DATA_DIR, "data"))
                        .withMembers(raftMembers)
                        .build())
                .build();
    }
}


java-raft框架之atomix进行分布式管理_atomix

运行成功后,会在程序根目录下生成对应的数据文件。
如上面代码中指定的文件路径为:db/partitions/datadb/partitions/system,则会将数据持久化到上面的目录中

leader选举

除了上面的map存储外,leader选举也是分布式系统中经常用到:

AsyncLeaderElector leaderElector = atomix.leaderElectorBuilder("leader")
                .withProtocol(MultiRaftProtocol.builder(groupName)
                        .withRecoveryStrategy(Recovery.RECOVER)
                        .withMaxRetries(MAX_RETRIES)
                        .withMaxTimeout(Duration.ofMillis(15000L))
                        .build())
                .withReadOnly(false)
                .build()
                .async();
        //获取出当前节点
        Member localMember = atomix.getMembershipService().getLocalMember();
        System.out.println("localMember:" + localMember.toString());
        String topic = "this is a topic";
        //根据某一topic选举出leader,返回的是选举为leader的节点
        Leadership leadership = (Leadership) leaderElector.run(topic, localMember.toString()).get();
        System.out.println("==========" + leadership);
        //get leadership
        Leadership topicLeadership = (Leadership) leaderElector.getLeadership(topic).get();
        System.out.println("------------>" + topicLeadership);
        //输出所有的topic对应的leader
        Map topicLeadershipMaps = (Map) leaderElector.getLeaderships().get();
        System.out.println("++++++++++++" + topicLeadershipMaps.toString());

输出结果为:

localMember:Member{id=node1, address=127.0.0.1:6789, host=127.0.0.1, properties={}}
==========Leadership{leader=Leader{id=Member{id=node1, address=127.0.0.1:6789, host=127.0.0.1, properties={}}, term=1, termStartTime=1675088739669}, candidates=[Member{id=node1, address=127.0.0.1:6789, host=127.0.0.1, properties={}}]}
------------>Leadership{leader=Leader{id=Member{id=node1, address=127.0.0.1:6789, host=127.0.0.1, properties={}}, term=1, termStartTime=1675088739669}, candidates=[Member{id=node1, address=127.0.0.1:6789, host=127.0.0.1, properties={}}]}
++++++++++++{this is a topic=Leadership{leader=Leader{id=Member{id=node1, address=127.0.0.1:6789, host=127.0.0.1, properties={}}, term=1, termStartTime=1675088739669}, candidates=[Member{id=node1, address=127.0.0.1:6789, host=127.0.0.1, properties={}}]}}

总结

atomix的api远不止本例中的两个,还有其他很多的api。

如分布式锁、分布式事务、分布式自增id、分布式队列、分布式信息号等,这些在atomix中都有实现,详细可见atomix的类方法:

java-raft框架之atomix进行分布式管理_raft_02

也正如当前所说,当前基于JAVA实现的atomix已经停止维护了。

如果要在生产环境中使用atomix,可以移步atomix的官网,获取在k8s环境下的新版atomix的使用方式,依然很强大。

java-raft框架之atomix进行分布式管理_集群_03

参考链接
https://baymaxhuang.github.io/2017/06/14/Kryo序列化及其在ONOS中的应用/


标签:127.0,java,0.1,atomix,io,import,raft,id
From: https://blog.51cto.com/u_2837193/6309221

相关文章

  • java整型 浮点型简单使用案例
    publicclassImoocStudent{publicstaticvoidmain(String[]args){inti1=2,i2=4;inti3=i1/i2;System.out.println("整型2除以整型4的结果为:"+i3);floatf1=2f,f2=4f;floatf3=f1/f2;......
  • Java面试题总结
    spring事务的传播机制 spring事务失效原因1,数据库不支持事务:比如mysql数据库,MyISAM(马儿爱涩m)引擎不持支事务,需要使用InnoDB引擎才行2,该类不受spring管理,使用@Transactional会失效:因为spring事务是基于aop动态代理实现的,需要从ioc容器中获取bean才能为该对象生成代理类,从而......
  • 37基于java的职工管理系统设计与实现
    本章节给大家带来一个基于java的职工管理系统设计与实现,可适用于员工管理系统,企业员工管理系统,公司员工管理系统,企业人事管理系统,基于java职工管理系统,前后端分离,员工考勤管理系统,职工奖惩管理系统,职员合同管理,HR管理系统,人事HR管理系统等;引言由于计算机的快速发展,企业员工管......
  • 插入排序Java版
    插入排序工作原理:从头开始遍历数组,如果发现当前项比前一项小,说明当前项应该插到前面,交换一下即可。利用双层for循环,第一层是遍历整个数组,第二层负责遍历当前所遍历到的位置之前的数组。/***@Author:翰林猿*@Description:插入排序**/publicclassInsert{  pu......
  • JAVA学习之枚举类和注解
    之后的知识点都是一些小的细的碎的知识点的大杂烩,于是就选择每天都建一个新博客,去记录知识点了。枚举简单介绍:1.枚举对应英文(enumeration,简称enum)。2.枚举是一组常量的集合。3.可以理解为:枚举是一种特殊的类,里面只包含一组有限的特定的对象。首先尝试用已有知识解决需求:自......
  • Java编程的逻辑
    chapter3类的基础3.3代码的组织机制包范围可见性如果什么修饰符都不写,它的可见性范围就是同一个包内,同一个包内的其他类可以访问,而其他包内的类则不可以访问。声明为protected不仅表明子类可以访问,还表明同一个包内的其他类可以访问,即使这些类不是子类也可以。总结来说,可......
  • Java中==和equals的区别
    在Java中“==”和“equals()”都是用于比较两个对象是否相等,但是他们之间还是有着许多不同之处。两者的区别“==”是一个操作符,用于比较两个操作数的值是否相等。如果操作数为值类型,比较的是值是否相等,如果操作数为引用类型,比较的是地址值是否相等。“equals()”是一个定义在Ob......
  • 深入理解之JavaScript之call, apply, bind方法
    在JavaScript中,call、apply和bind是Function对象自带的三个方法,这三个方法的主要作用是改变函数执行时的上下文,再具体一点就是改变函数运行时的this指向。Function.prototype.call()call()方法调用一个函数,其具有一个指定的this值和多个参数(参数的列表)。fun.call(thisArg,a......
  • java面试题--Redis
    一、说一下redis的持久化机制原理?RDB文件:redisdatabase。存储的是某个时间点的数据库内容的快照,是结果。redis默认的持久化策略。落盘策略:使用SAVE或者BGSAVE命令。(1)SAVE:有主线程执行,会阻塞客户端。(2)BGSAVE:会fork出一个子进程,不会出现阻塞问题。子进程使用写时拷贝的策......
  • javascript小技巧(六)
    操作EXECL<scriptlanguage="javascript">functionjStartExcel(){varxls=newActiveXObject("Excel.Application");xls.visible=true;varnewBook=xls.Workbooks.Add;newBook.Worksheets.Add;newBook.Worksheets(1).Activa......