副问题[/!--empirenews.page--]

最简朴的方法
基于数据库 auto_increment_increment 来获取 ID。起首在数据库中建设一张 sequence 表,个中 seq_name 用以区分差异营业标识,从而实现支持多种营业场景下的自增 ID, current_value 为当前值, _increment 为步长,可支持漫衍式数据库的哈希计策。
- CREATE TABLE `sequence` (
- `seq_name` varchar(200) NOT NULL,
- `current_value` bigint(20) NOT NULL,
- `_increment` int(4) NOT NULL,
- PRIMARY KEY (`seq_name`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8
通过 SELECT LAST_INSERT_ID() 要领,更新 sequence 表,举办 ID 递增,并同时获取前次更新的值。这里留意, current_value = LAST_INSERT_ID(current_value + _increment) 将更新的 ID 赋值给了 LAST_INSERT_ID ,不然返回的将是行 id。
- UPDATE sequence
- SET
- current_value = LAST_INSERT_ID(current_value + _increment)
- WHERE
- seq_name = #{seqName}
最后 Dao 提供处事,必要提示的是留意数据库的事宜断绝级别,假如将 getSeq() 要领放到 Service 中有事宜的要领里,将呈现题目,由于数据库事宜开启会建设一张视图,在事宜没有提交之前,更新的 ID 还没有被提交到数据库中,这在多线程并发操纵的环境下,假如事宜里的其他要教育致机能慢了,也许呈现两个哀求获取到沟通的 ID,以是办理要领一是不要将 getSeq() 要领放到有事宜的要领里,另一种就是将 getSeq() 要领的断绝界别为 PROPAGATION_REQUIRES_NEW ,实现开启新事宜,外层事宜不会影响内部事宜的提交。
- @Autowired
- private SeqDao seqDao;
- @Autowired
- private PlatformTransactionManager transactionManager;
- @Override
- public long getSeq(final String seqName) throws Exception {
- TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
- // 事宜举动,独立于外部事物独立运行
- transactionTemplate
- .setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
- return (Long) transactionTemplate.execute(new TransactionCallback() {
- public Object doInTransaction(TransactionStatus status) {
- try {
- Seq seq = new Seq();
- seq.setSeqName(seqName);
- if (seqDao.update(seq) == 0) {
- throw new RuntimeException("seq update failure.");
- }
- return seq.getId();
- } catch (Exception e) {
- throw new RuntimeException("seq update error.");
- }
- }
- });
- }
稍伟大一点的要领
上述的要领的题目,想必各人都知道,就是每次获取 ID 都要挪用数据库,在高并发的环境下会对数据库发生极大的压力,我们的改造要领也很简朴,就是一次申请一个段的 ID,然后发到内存里,每次获取 ID 先从内存里取,当内存中的 ID 段所有被获取完毕,则再一次挪用数据库从头申请一个新的 ID 段。
同样稀有据库表的计划,通过 Name 区分营业,用 ID 标明已经申请到的最大值。虽然假如是漫衍式架构,也可以通过增进步长属性来实现。
- CREATE TABLE `sequence_value` (
- `Name` varbinary(50) DEFAULT NULL,
- `ID` int(11) DEFAULT NULL
- ) ENGINE = InnoDB DEFAULT CHARSET = utf8
Step 是 ID 段的内存工具,有两个属性,个中 currentValue 当前的行使到的值,endValue 是内存申请的最大值。
- class Step {
- private long currentValue;
- private long endValue;
- Step(long currentValue, long endValue) {
- this.currentValue = currentValue;
- this.endValue = endValue;
- }
- public void setCurrentValue(long currentValue) {
- this.currentValue = currentValue;
- }
- public void setEndValue(long endValue) {
- this.endValue = endValue;
- }
- public long incrementAndGet() {
- return ++currentValue;
- }
- }
(编辑:湖南网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|