转载

获取id 的一种策略

从数据库中批量(step个)拿出Id,然后使用,待消耗完后再批量拿出Id

key1 = genKey+"##"+subKey;

三个并发Map:

mapLock:判断是否存在锁

mapGenId:保存每次的currNo值

mapMaxId:保存每次currNo+step后的值

三个ConcurrentHashMap的key都为 key1

大体思路:

一、由genKey、subKey构建一个锁,获取Id值时先判断是否存在锁,当不存在锁时,先初始化

初始化:

从数据库中取出currNo

1、若currNo为0(第一次)

将当前currNo设为0并放入mapGenId中

表中插入一条currNo为step的记录,返回MaxId的值为step

2、若currNo不为0

将当前currNo设为数据库中查出的currNo,并放入mapGenId中

将数据库中查出的currNo,加上step后更新,返回MaxId的值为currNo+step

将MaxId置入保存最大值的并发map mapMaxId中

再生成key为key1的锁

二、初始化完成后,取得锁(若已存在锁,则取出并锁住),从mapGenId、mapMaxId中分别取得当前currNo值和当前最大MaxId值

若 mapGenId中取出的值(当前currNo值)<= mapMaxId中的值(每次的最大currNo值)时,说明上次取得 step个Id还没有消耗完,所以直接当前currNo+1即可,否则说明

已消耗完,需要重新从数据库中取数据

三、若需要重新取数据,则跟初始化时currNo不为0的情况相同

加上 step后更新数据库,然后分别设置mapGenId、mapMaxId即可

DB:

获取id 的一种策略 获取id 的一种策略

使用:

long lPointId = HttpUtil.getId("testSQL","userPoint");

public static Long getId(String genKey,String subKey){   Long lId = 0l;     lId = GetTableId.getCurrentId(genKey, subKey);   return lId;  }
public class GetTableId {  static Logger logger = Logger.getLogger(GetTableId.class);      /**   * 获取ID   * @param genKey   * @param subKey   * @return   */  public static Long getCurrentId(String genKey,String subKey){   GenId genIdVo = new GenId();   genIdVo.setGenKey(genKey);   genIdVo.setSubKey(subKey);      Long currNo = getGenId(genIdVo);   return currNo;  }      public static Long getGenId(GenId genIdVo){   String subKey = genIdVo.getSubKey();    String genKey = genIdVo.getGenKey();      if (!GenIdHelper.getInstance().containsKey(genKey, subKey)) {    initGenIdByDB(genIdVo);  //初始化ID hash   }   synchronized (GenIdHelper.getInstance().getLockObject(genKey, subKey)) {        Long currNo = getGenIdByCache(genKey, subKey);        logger.info("return currNo = " + currNo);        return currNo;    }   }   /**   * 第一次加载   */  private static void initGenIdByDB(GenId genIdVo) {   String subKey = genIdVo.getSubKey();    String genKey = genIdVo.getGenKey();    logger.info("genKey = " + genKey + ": subKey = " + subKey);    GenId vo = getGenIdLock(genKey, subKey);    if (GenIdHelper.getInstance().containsKey(genKey, subKey)) {     logger.info("other thread is return" + genKey + ":" + subKey);     return;   }    Long step = GenIdConstant.GenIdStep;    Long currNo = 0L;    if (vo.getCurrNo() == 0) {     currNo = insertGenId(genKey, subKey, step);     logger.info("no live frist is currNo =" + currNo);     GenIdHelper.getInstance().setGenIDValue(genKey, subKey, new Long(0));    } else {     updateGenIdVO(genKey, subKey);        currNo = vo.getCurrNo() + GenIdHelper.getInstance().getGenIdSetp(genKey, subKey);     GenIdHelper.getInstance().setGenIDValue(genKey, subKey, vo.getCurrNo());     logger.info("live frist is currNo =" + currNo);    }    setGenIdCacheMap(genKey, subKey, currNo);    GenIdHelper.getInstance().setLockObject(genIdVo.getGenKey(),genIdVo.getSubKey());   }    /**   * 设置CACHEMAP里的值   *    * @param genKey   * @param subKey   * @param currNo   */  private static void setGenIdCacheMap(String genKey, String subKey, Long currNo) {    logger.info("setGenIdCacheMap genKey = " + genKey + ": subKey = " + subKey + ": currNo = " + currNo);    GenIdHelper.getInstance().setMaxID(genKey, subKey, currNo);  }    /**   * 如果数据库不存在就插入   *    * @param genKey   * @param subKey   * @param step   * insert into genId (currNo, genKey, subKey, updateTime) values     ({currNo}, {genKey}, {subKey}, now());   */  private static Long insertGenId(String genKey, String subKey, Long step) {     CDO cdoRequest = new CDO();   CDO cdoResponse = new CDO();   cdoRequest.setStringValue(ITransService.SERVICENAME_KEY,"CommonService");   cdoRequest.setStringValue(ITransService.TRANSNAME_KEY, "insertGenId");   cdoRequest.setStringValue("subKey", subKey);   cdoRequest.setStringValue("genKey", genKey);   cdoRequest.setLongValue("currNo", step);   Return ret = getServiceBus().handleTrans(cdoRequest, cdoResponse);   if (ret.getCode() != 0) {    logger.error("insertGenId error.");   }    return step;  }    /**   * 从数据库里取的时候先锁住这条记录   *    * @param genKey   * @param subKey   * @return   */  private static GenId getGenIdLock(String genKey, String subKey) {   long lId = 0;   logger.info("islock genKey = " + genKey + ": subKey = " + subKey);    GenId genIdVo = new GenId();    genIdVo.setSubKey(subKey);    genIdVo.setGenKey(genKey);      CDO cdoRequest = new CDO();   CDO cdoResponse = new CDO();      cdoRequest.setStringValue(ITransService.SERVICENAME_KEY,"CommonService");   cdoRequest.setStringValue(ITransService.TRANSNAME_KEY, "getGenId");   cdoRequest.setStringValue("subKey", subKey);   cdoRequest.setStringValue("genKey", genKey);   Return ret = getServiceBus().handleTrans(cdoRequest, cdoResponse);   if (ret.getCode() == 0) {    if(cdoResponse.exists("cdoGenId")){     lId = cdoResponse.getLongValue("cdoGenId");    }   }   genIdVo.setCurrNo(lId);   return genIdVo;  }    /**   * 更新数据的操作   *    * @param subKey   * @param genKey   * @param currNo   * update genId  set currNo = currNo + {currNo},updateTime=now()      where genKey = {genKey} and subKey = {subKey}   */  private static void updateGenIdVO(String genKey, String subKey) {   logger.info("updateGenIdVO genKey = " + genKey + ": subKey = " + subKey);    long currNo = GenIdConstant.GenIdStep;    CDO cdoRequest = new CDO();   CDO cdoResponse = new CDO();   cdoRequest.setStringValue(ITransService.SERVICENAME_KEY,"CommonService");   cdoRequest.setStringValue(ITransService.TRANSNAME_KEY, "updateGenIdByPk");   cdoRequest.setStringValue("subKey", subKey);   cdoRequest.setStringValue("genKey", genKey);   cdoRequest.setLongValue("currNo", currNo);   Return ret = getServiceBus().handleTrans(cdoRequest, cdoResponse);   if (ret.getCode() != 0) {    logger.error("updateGenIdByPk error.");   }   }    /**   * 比较当前值和最大值,返回自增ID   * @param genKey   * @param subKey   * @return   */  private static Long getGenIdByCache(String genKey, String subKey) {      Long maxId = GenIdHelper.getInstance().getMaxID(genKey, subKey) ;      logger.info("getGenIdByCache maxId = " + maxId);      Long currNo = GenIdHelper.getInstance().getGenIDValue(genKey, subKey);      logger.info("currNo maxId = " + currNo);      if(currNo >= maxId){        GenId genIdVo = new GenId();        genIdVo.setGenKey(genKey);        genIdVo.setSubKey(subKey);        setGenIdByDB(genIdVo);      }      GenIdHelper.getInstance().setGenIDValue(genKey, subKey, currNo + 1);    return currNo + 1;  }      /**   * 如果大于最大值就从数据库里取   */  private static void setGenIdByDB(GenId genIdVo) {    String subKey = genIdVo.getSubKey();    String genKey = genIdVo.getGenKey();    logger.info("genKey = " + genKey + ": subKey = " + subKey);    GenId vo = getGenIdLock(genKey, subKey);      updateGenIdVO(genKey, subKey);    Long currNo = vo.getCurrNo() + GenIdConstant.GenIdStep;    logger.info("setGenIdByDB currNo = " + currNo);    setGenIdCacheMap(genKey,subKey, currNo);   }  }
public class GenId {    private Long genId;    private Long currNo;    private String genKey;    private String subKey;         ... }
public class GenIdConstant {   public final static String SPLITFLAG = "##";    public final static Long GenIdStep  = new Long(100);    public final static String RESULTTYPEKEYNAME  = "resultCode";    public final static String RESULTCURRNONAME  = "currNo";    }

处理并发工具类:

public class GenIdHelper {    //每条记录的线程锁  private static ConcurrentHashMap<String, Object> mapLock = new ConcurrentHashMap<String, Object>();    //每个记录的步长  private static ConcurrentHashMap<String, Long> mapStep = new ConcurrentHashMap<String, Long>();    //每个记录的ID值  private static ConcurrentHashMap<String, Long> mapGenId = new ConcurrentHashMap<String, Long>();    //每个记录的MAXID值  private static ConcurrentHashMap<String, Long> mapMaxId = new ConcurrentHashMap<String, Long>();    /*   * 懒汉,线程安全   */  private static GenIdHelper cc = null;    private GenIdHelper(){}    public static synchronized GenIdHelper getInstance() {   if (cc == null){      cc = new GenIdHelper();   }   return cc;  }    /**   * 设置每个自增ID的线程锁对象   *    */   protected  void setLockObject(String genKey, String subKey){      mapLock.put(buildLockKey(genKey, subKey), new Object());  }    /**   * 设置每个自增ID的线程锁对象   *    */   protected Object getLockObject(String genKey, String subKey){      return mapLock.get(buildLockKey(genKey, subKey));  }    /**   * 设置每个自增ID的最大值   *    */   protected  void setMaxID(String genKey, String subKey, Long maxId){      mapMaxId.put(buildLockKey(genKey, subKey), maxId);  }    /**   * 获取自增ID的最大值   *    */   protected  Long getMaxID(String genKey, String subKey){      return mapMaxId.get(buildLockKey(genKey, subKey));  }    /**   * 获取自增ID的值   *    */   protected  Long getGenIDValue(String genKey, String subKey){      return mapGenId.get(buildLockKey(genKey, subKey));  }    /**   * 设置获取自增ID的值   *    */   protected void setGenIDValue(String genKey, String subKey, Long currNo){      mapGenId.put(buildLockKey(genKey, subKey), currNo);  }    /**   * 判断是否存在线程锁对象   * @param key   */   protected  boolean containsKey(String genKey, String subKey){      return mapLock.containsKey(buildLockKey(genKey, subKey));  }    private  String buildLockKey(String genKey, String subKey){      return genKey + GenIdConstant.SPLITFLAG + subKey;  }    protected Long getGenIdSetp(String genKey, String subKey){      Long step = mapStep.get(buildLockKey(genKey, subKey));      if(step == null){        step = GenIdConstant.GenIdStep;   }      return step;     }  }

。。。

正文到此结束
Loading...