クラスタ環境における雪花アルゴリズムのグローバル一意マシンIDポリシーの生成


雪花アルゴリズムはデータidを生成するのに非常に良い方法であり、機械idは雪花アルゴリズムの不可分な一部である.しかし、クラスタアプリケーションでは、異なるマシンに自動的に異なるマシンidを生成させる従来の方法は、各マシンに対して個別の構成を行うことであるが、これはクラスタレベルの拡張に不利であり、操作過程が非常に複雑であるため、各マシンはクラスタ環境下で頭が痛い問題である.現在spring+redisを借りて、勝手なレベルの拡張をサポートし、肥腸が使いやすい戦略を提供しています.大まかな戦略は4つのステップに分けられる:1.マシンipに対してhashを行い、ある(あなたのマシンの個数より大きい)数を型取り、初期のマシンIDとする.2.マシンidをredisに格納する(登録).3.このように,各機器が初期化されたときにredisに1つの数を登録し,この数が登録されていれば+1を再登録する.4.springコンテナの破棄時にredisから登録情報を削除します.次に、実装コードを示します.
@Service("machineIdUtil")
public class MachineIdUtil {
//  
    private static Logger logger = LogUtil.getLogger(MachineIdUtil.class);
  /**
  *redis   
  */
    @Autowired
    private Cluster jimClient;
    /**
     *   id
     */
    public static Integer machine_id;
    /**
     *   ip  
     */
    private static String localIp;
    private static TimeUnit timeUnit = TimeUnit.DAYS;

    /**
     * hash  IP       ID
     */
    @PostConstruct
    public void initMachineId() throws Exception {
        localIp = IpUtil.getInet4Address();

        Long ip_ = Long.parseLong(localIp.replaceAll("\\.", ""));
        //   128,     Ip     。
        machine_id = ip_.hashCode()% 128;
        //      ID
        createMachineId();
        logger.info("    machine_id :{}", machine_id);
        SnowFlakeGenerator.initMachineId(machine_id);
    }

    /**
     *            
     */
    @PreDestroy
    public void destroyMachineId() {
        jimClient.del(RedisConstant.OPLOG_MACHINE_ID_kEY + machine_id);
    }


    /**
     *    :      id
     *
     * @return
     */
    public Integer createMachineId() {
        try {
            // redis  ,       
            Boolean aBoolean = registMachine(machine_id);
            //    
            if (aBoolean) {
                //            
                updateExpTimeThread();
                //    Id
                return machine_id;
            }
            //         .    ,     
            if (!checkIfCanRegist()) {
                //    ,     
                Profiler.businessAlarm("medicine-oplog-createMachineId", System.currentTimeMillis(), "128         !");
                return machine_id;
            }
            logger.info("createMachineId->ip:{},machineId:{}, time:{}", localIp, machine_id, DateUtil.getDate());

            //    
            createMachineId();
        } catch (Exception e) {
            getRandomMachineId();
            return machine_id;
        }
        getRandomMachineId();
        return machine_id;
    }

    /**
     *          
     *
     * @return
     */
    private Boolean checkIfCanRegist() {
        Boolean flag = true;
        //  0~127        IP     
        for (int i = 0; i <= 127; i++) {
            flag = jimClient.exists(RedisConstant.OPLOG_MACHINE_ID_kEY + i);
            //     。         。    i
            if (!flag) {
                machine_id = i;
                break;
            }
        }
        return !flag;
    }

    /**
     * 1.      
     *   ,           ip    
     */
    private void updateExpTimeThread() {
        //            :
        //1. 23          
        new Timer(localIp).schedule(new TimerTask() {
            @Override
            public void run() {
                //      ip   ip    ,       ,           ID
                Boolean b = checkIsLocalIp(String.valueOf(machine_id));
                if (b) {
                    logger.info("       ip:{},machineId:{}, time:{}", localIp, machine_id, DateUtil.getDate("yyyy-MM-dd HH:mm:ss"));
                    jimClient.expire(RedisConstant.OPLOG_MACHINE_ID_kEY + machine_id, 1, timeUnit);
                } else {
                    logger.info("      ID ip:{},machineId:{}, time:{}", localIp, machine_id, DateUtil.getDate("yyyy-MM-dd HH:mm:ss"));
                    //      ID,          ID
                    getRandomMachineId();
                    //         id
                    createMachineId();
                    //        ID
                    SnowFlakeGenerator.initMachineId(machine_id);
                    //      
                    logger.info("Timer->thread->name:{}", Thread.currentThread().getName());
                    this.cancel();
                }
            }
        }, 10 * 1000, 1000 * 60 * 60 * 23);
    }

    /**
     *   1~127   
     */
    public void getRandomMachineId() {
        machine_id = (int) (Math.random() * 127);
    }

    /**
     *   ID    
     */
    public void incMachineId() {
        if (machine_id >= 127) {
            machine_id = 0;
        } else {
            machine_id += 1;
        }
    }

    /**
     * @param mechineId
     * @return
     */
    private Boolean checkIsLocalIp(String mechineId) {
        String ip = jimClient.get(RedisConstant.OPLOG_MACHINE_ID_kEY + mechineId);
        logger.info("checkIsLocalIp->ip:{}", ip);
        return localIp.equals(ip);
    }

    /**
     * 1.    
     * 2.      
     *
     * @param mechineId    0~127
     * @return
     */
    private Boolean registMachine(Integer mechineId) throws Exception {
        return jimClient.set(RedisConstant.OPLOG_MACHINE_ID_kEY + mechineId, localIp, 1, TimeUnit.DAYS, false);
    }


}