分布式数据库部署主要分为两种,一种是读写分离。这个需要弄主从数据库。主要是写的时候写主数据库,读的时候读从数据库。分散读取压力,对于读多写少的系统有利于
提高其性能。还有一种是分布式存储,这种主要是将一张表拆分成多张分表部署到各个服务器中,主要针对写操作频繁的系统,如微博,淘宝的订单系统。
这两种方案都会遇到主键类型及生成方式的问题,还有主从数据库不同步和主键冲突问题。
主键类型主要有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自增。。。