美文网首页分布式架构
一个基于RMI的ID生成器简单模型

一个基于RMI的ID生成器简单模型

作者: 简单是美美 | 来源:发表于2020-03-07 10:40 被阅读0次

    1. 概述

      ID生成器是IM,电商系统中绕不过去的一个组件。对于系统中发生的每个事件,如IM发送的每一条消息,电商平台的每个订单都需要生成一个ID,这个ID成为事件的唯一标识,提供之后的跟踪与检索工作。网络上微信与美团等知名厂商都分享了自己的ID生成算法,对于大型系统,ID生成算法都是分布式ID算法,基础算法使用了snowflake或分段自增等算法。
      ID生成器的调用通常为RPC方式,目前常用的使用方式有GRPC,HTTP等调用方式。本文介绍如何使用JAVA RMI的方式快速实现一个简单ID生成器。

    2.接口定义

      RMI的接口供ID生成器和调用ID生成器的客户端使用,定义如下:

    package com.kedacom.rmiinterface;
    
    import java.rmi.Remote;
    import java.rmi.RemoteException;
    
    /**
     * @author zhang.kai
     *
     */
    public interface IIdGen extends Remote{
        
        public long getNextId() throws RemoteException;
    
    }
    

    3. 服务端

      服务端实现ID的分发,这里使用一个简单的自增算法,可以设定ID的初始值(这里简单地以服务初始化时间作为初始值),定义如下:

    package com.kedacom.rmiserver.service;
    
    import java.rmi.RemoteException;
    import java.rmi.server.UnicastRemoteObject;
    import java.util.concurrent.atomic.AtomicLong;
    
    import com.kedacom.rmiinterface.IIdGen;
    
    /**
     * @author zhang.kai
     *
     */
    
    public class IdGenService extends UnicastRemoteObject implements IIdGen{
        
        
        private static final long serialVersionUID = -3742466067930952734L;
        
        private final AtomicLong idSeed ;
        
        /**
         * @param port
         * @throws RemoteException
         */
        public IdGenService() throws RemoteException {
            super();
            idSeed = new AtomicLong(getInitValue()); 
        }
    
    
        @Override
        public long getNextId() throws RemoteException {
            
            return idSeed.getAndIncrement();
        }
        
        /**
         * 获取ID的初始值
         * @return
         */
        private long getInitValue() {
            
            return System.currentTimeMillis();
        }
        
    }
    

      服务对象的注册代码如下:

    @Override
        public void run(ApplicationArguments args) throws Exception {
            
            //设置rmi服务端的hostname,该值与远程调用对象绑定,用于客户端寻址
            System.setProperty("java.rmi.server.hostname",rmiSvrHostname);
            
            //创建注册中心
            Registry reg = LocateRegistry.createRegistry(RmiConfigConsts.RMI_REGISTRY_PORT);
            log.info("registry:"+reg);
            
            //注册远程对象
            IdGenService idgObj = new IdGenService();
            log.info("remote obj:{}",idgObj);
            Registry registry = LocateRegistry.getRegistry(RmiConfigConsts.RMI_REGISTRY_PORT);
            registry.bind(RmiConfigConsts.IDGEN_RMI_OBJECT_NAME, idgObj);
            
            
            log.info("idgen rmi obj ready!");
        }
    

    4.客户端调用

      客户端调用代码比较简单,如下:

    @Override
        public void run(ApplicationArguments args) throws Exception {
            // TODO Auto-generated method stub
            // 获取注册中心
            Registry registry = LocateRegistry.getRegistry(rmiSvrHostname, RmiConfigConsts.RMI_REGISTRY_PORT);
            log.info("get registry");
    
            // 在注册中心中查找远程对象
            IIdGen idgen = (IIdGen) registry.lookup(RmiConfigConsts.IDGEN_RMI_OBJECT_NAME);
            log.info("get idgen:{}", idgen);
    
            // 循环调用该接口
            for (int i = 0; i < 10; i++) {
                log.info("{} remote idgen:{}", i, idgen.getNextId());
            }
        }
    

    5.小结

      JAVA RMI是JDK提供的一种原生RPC方式,使用的对象序列化方式为JAVA对象的序列化方式,从测试的效率来看,在网络环境下,一次调用的时间开销在1ms以内。从实现方式上来看,代码也比较简单,缺点是与JAVA语言强绑定。本文只是示例了一个最简单的ID生成算法,如果有更复杂逻辑在算法中,应考虑线程安全问题。本文的示例代码可从https://github.com/solarkai/IdGenRmi获取。

    相关文章

      网友评论

        本文标题:一个基于RMI的ID生成器简单模型

        本文链接:https://www.haomeiwen.com/subject/dexqdhtx.html