分布式数据库主键id生成策略

孤街浪徒 提交于 2019-11-27 23:51:23

分布式数据库部署主要分为两种,一种是读写分离。这个需要弄主从数据库。主要是写的时候写主数据库,读的时候读从数据库。分散读取压力,对于读多写少的系统有利于

提高其性能。还有一种是分布式存储,这种主要是将一张表拆分成多张分表部署到各个服务器中,主要针对写操作频繁的系统,如微博,淘宝的订单系统。

这两种方案都会遇到主键类型及生成方式的问题,还有主从数据库不同步和主键冲突问题。

主键类型主要有GUID和数字类型,这里我们不讨论GUID;

数字主键主要存在唯一性、可同步性两个方面的不足

可同步性:可以不使用主键自增方案。

唯一性:可以单独使用存储过程生成ID,设置主键ID的初始值步长和最大值,及所对应的表,当然主从数据库的主表和分表初始值和最大值是不一样的,一样的话会造成主键重复。

存储过程:

-- ----------------------------
-- Procedure structure for getId
-- ----------------------------
DROP PROCEDURE IF EXISTS `getId`;
DELIMITER ;;
CREATE DEFINER=`sawyer`@`%` PROCEDURE `getId`(OUT aId INT, OUT aIdEnd INT, aType TINYINT)
BEGIN
	DECLARE id,eid,iStep INT;
	DECLARE rev TINYINT;
	SELECT Current_ID,END,Step,REVERSE INTO id,eid,iStep,rev FROM t_id WHERE TYPE=aType;
	IF id<eid THEN
		SET aId = id;
		IF id+iStep >= eid THEN
			SET aIdEnd = eid;
			IF rev = 1 THEN
				UPDATE t_id SET Current_ID=Start_ID WHERE TYPE=aType;
			ELSE
				UPDATE t_id SET Current_ID=eid WHERE TYPE=aType;
			END IF;
		ELSE
			SET aIdEnd = id+iStep;
			UPDATE t_id SET Current_ID=aIdEnd WHERE TYPE=aType;
		END IF;
	ELSE
		SET aId = 0, aIdEnd = 0;
	END IF;
END
;;
DELIMITER ;

 主表

从表

 

 

写一个java类去调用这个存储过程生成主键。

/*    */ package btir.dao.jdbc;
/*    */ 
/*    */ import btir.BtirException;
/*    */ import btir.dao.ha.DBMgr;
/*    */ import btir.dao.ha.PooledStmt;
/*    */ import btir.utils.MiscUtil;
/*    */ import org.apache.commons.logging.Log;
/*    */ import org.apache.commons.logging.LogFactory;
/*    */ 
/*    */ 
/*    */ 
/*    */ 
/*    */ 
/*    */ 
/*    */ 
/*    */ public class IdHolder
/*    */ {
/*    */   public static final int NO_ID_AVAILABLE = 0;
/* 19 */   private static final Log log = LogFactory.getLog(IdHolder.class);
/*    */   
/*    */ 
/*    */ 
/*    */   private int current;
/*    */   
/*    */ 
/*    */   private int end;
/*    */   
/*    */ 
/*    */ 
/*    */   public synchronized int getId(byte type, int stmtId)
/*    */   {
/* 32 */     if (end <= current)
/*    */     {
/*    */       try
/*    */       {
/* 36 */         PooledStmt stmt = DBMgr.borrowSingleStmt(stmtId);
/*    */         
/*    */ 
/* 39 */         stmt.setByte(3, type);
/* 40 */         stmt.executeUpdate();
/* 41 */         current = stmt.getInt(1);
/* 42 */         end = stmt.getInt(2);
/* 43 */         stmt.returnMe();
/*    */       } catch (BtirException e) {
/* 45 */         current = (end = 0);
/* 46 */         log.error("can't get id for type=" + type);
/* 47 */         log.error(MiscUtil.traceInfo(e));
/* 48 */         return 0;
/*    */       }
/* 50 */       if (end <= current)
/* 51 */         return 0;
/*    */     }
/* 53 */     return current++;
/*    */   }
/*    */   
/*    */   public synchronized int getId(byte type, PooledStmt stmt) {
/* 57 */     if (end <= current) {
/*    */       try {
/* 59 */         stmt.setByte(3, type);
/* 60 */         stmt.executeUpdate();
/* 61 */         current = stmt.getInt(1);
/* 62 */         end = stmt.getInt(2);
/*    */       } catch (BtirException e) {
/* 64 */         current = (end = 0);
/* 65 */         return 0;
/*    */       }
/* 67 */       if (end <= current)
/* 68 */         return 0;
/*    */     }
/* 70 */     return current++;
/*    */   }
/*    */ }

 上面这段代码主要是调用存储过程,对应配置的表的ID自增。。。

转载于:https://www.cnblogs.com/JAYIT/p/5018156.html

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!