Authored by chenchao

use database config control sequence of order code

  1 +package com.yohoufo.order.model.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * Created by chao.chen on 2019/3/8.
  7 + */
  8 +@Data
  9 +public class OrderCodeRule {
  10 +
  11 +
  12 + private String env;
  13 +}
@@ -70,7 +70,9 @@ public class CacheKeyBuilder { @@ -70,7 +70,9 @@ public class CacheKeyBuilder {
70 70
71 SELLER_EARNEST_MONEY_CONFIG("ufo:order:seller:earnestMoney:config",""), 71 SELLER_EARNEST_MONEY_CONFIG("ufo:order:seller:earnestMoney:config",""),
72 72
73 - PRESALE_THRESHOLD("ufo:order:presale:threshold", "") 73 + PRESALE_THRESHOLD("ufo:order:presale:threshold", ""),
  74 +
  75 + ORDER_CODE_RULE("ufo:order:code:rule", "")
74 ; 76 ;
75 77
76 private String fix; 78 private String fix;
@@ -12,6 +12,7 @@ import com.yohoufo.dal.order.MetaConfigMapper; @@ -12,6 +12,7 @@ import com.yohoufo.dal.order.MetaConfigMapper;
12 import com.yohoufo.dal.order.model.MetaConfig; 12 import com.yohoufo.dal.order.model.MetaConfig;
13 import com.yohoufo.order.model.dto.BuyerPenalty; 13 import com.yohoufo.order.model.dto.BuyerPenalty;
14 import com.yohoufo.order.model.dto.EarnestMoney; 14 import com.yohoufo.order.model.dto.EarnestMoney;
  15 +import com.yohoufo.order.model.dto.OrderCodeRule;
15 import com.yohoufo.order.model.dto.PreSaleOrderConfig; 16 import com.yohoufo.order.model.dto.PreSaleOrderConfig;
16 import com.yohoufo.order.service.cache.CacheKeyBuilder; 17 import com.yohoufo.order.service.cache.CacheKeyBuilder;
17 import com.yohoufo.order.service.cache.ExpiredTime; 18 import com.yohoufo.order.service.cache.ExpiredTime;
@@ -247,4 +248,22 @@ public class MetaConfigService { @@ -247,4 +248,22 @@ public class MetaConfigService {
247 return psoc; 248 return psoc;
248 } 249 }
249 250
  251 + /**
  252 + * 获取配置的订单号生成规则
  253 + * @return
  254 + */
  255 + public OrderCodeRule getOrderCodeRule(){
  256 + CacheKeyBuilder.KeyTemp kt = CacheKeyBuilder.KeyTemp.ORDER_CODE_RULE;
  257 + RedisKeyBuilder rkb = kt.builderKeyOnlyFixed();
  258 + final String key = MetaConfigKey.ORDER_CODE_RULE;
  259 + String configVal = new DataProcesser(rkb, key, ExpiredTime.ORDER_BASE_CONFIG).getConfigVal();;
  260 + OrderCodeRule ocr = new OrderCodeRule();
  261 + try{
  262 + ocr = JSONObject.parseObject(configVal, OrderCodeRule.class);
  263 + }catch (Exception ex){
  264 + logger.warn("in getOrderCodeRule parseObject fail, metaVal {}", configVal, ex);
  265 + }
  266 + return ocr;
  267 + }
  268 +
250 } 269 }
1 package com.yohoufo.order.service.support.codegenerator.impl; 1 package com.yohoufo.order.service.support.codegenerator.impl;
2 2
3 import com.yohobuy.ufo.model.order.common.OrderCodeType; 3 import com.yohobuy.ufo.model.order.common.OrderCodeType;
  4 +import com.yohobuy.ufo.model.order.constants.OpsEnv;
  5 +import com.yohoufo.order.model.dto.OrderCodeRule;
  6 +import com.yohoufo.order.service.impl.MetaConfigService;
4 import com.yohoufo.order.service.support.codegenerator.OrderCodeGenerator; 7 import com.yohoufo.order.service.support.codegenerator.OrderCodeGenerator;
5 import com.yohoufo.order.service.support.codegenerator.bean.CodeBitMeta; 8 import com.yohoufo.order.service.support.codegenerator.bean.CodeBitMeta;
6 import com.yohoufo.order.service.support.codegenerator.bean.CodeMeta; 9 import com.yohoufo.order.service.support.codegenerator.bean.CodeMeta;
@@ -31,6 +34,9 @@ public class OrderCodeGeneratorImpl implements OrderCodeGenerator { @@ -31,6 +34,9 @@ public class OrderCodeGeneratorImpl implements OrderCodeGenerator {
31 @Autowired 34 @Autowired
32 MachineIdProvider machineIdProvider; 35 MachineIdProvider machineIdProvider;
33 36
  37 + @Autowired
  38 + MetaConfigService metaConfigService;
  39 +
34 long machineId = 0l; 40 long machineId = 0l;
35 41
36 @PostConstruct 42 @PostConstruct
@@ -41,7 +47,13 @@ public class OrderCodeGeneratorImpl implements OrderCodeGenerator { @@ -41,7 +47,13 @@ public class OrderCodeGeneratorImpl implements OrderCodeGenerator {
41 } 47 }
42 48
43 if (idPopulator == null){ 49 if (idPopulator == null){
44 - idPopulator = new AtomicIdPopulator(); 50 +
  51 + SequenceStrategy.SingleData sssd = createSequence();
  52 + long seq = sssd.start;
  53 +
  54 + AtomicIdPopulator.Variant variant = new AtomicIdPopulator().new Variant(seq);
  55 +
  56 + idPopulator = new AtomicIdPopulator(variant);
45 } 57 }
46 58
47 machineId = machineIdProvider.getMachineId(); 59 machineId = machineIdProvider.getMachineId();
@@ -50,6 +62,31 @@ public class OrderCodeGeneratorImpl implements OrderCodeGenerator { @@ -50,6 +62,31 @@ public class OrderCodeGeneratorImpl implements OrderCodeGenerator {
50 validateMachineId(this.machineId); 62 validateMachineId(this.machineId);
51 } 63 }
52 64
  65 + private SequenceStrategy.SingleData createSequence(){
  66 + OrderCodeRule ocr = metaConfigService.getOrderCodeRule();
  67 + Long seq = 0L;
  68 + String env = null;
  69 + boolean envIsNull = false;
  70 + if (ocr==null || (envIsNull = ((env=ocr.getEnv()) == null))){
  71 + log.warn("in order code generator env use prd, OrderCodeRule {}", ocr);
  72 + }
  73 + //明确指定了配置使用非生产环境时,序列号从1000开始
  74 + if (!envIsNull && !OpsEnv.PRD.getName().equalsIgnoreCase(env)){
  75 + seq = 1000L;
  76 + log.info("in order code generator env use not prd config, OrderCodeRule {} seq {}", ocr, seq);
  77 + }
  78 + log.info("in order code generator init config, OrderCodeRule {} seq {}", ocr, seq);
  79 + /*
  80 + *这是常驻内存的方式,其实很不妥,运维不方便;
  81 + * 数据库修改后需要重新发布工程才能获取新值
  82 + */
  83 + SequenceStrategy.SingleData sssd = SequenceStrategy.SingleData.create(env, seq);
  84 +
  85 + return sssd;
  86 + }
  87 +
  88 +
  89 +
53 public long generate(OrderCodeType type) { 90 public long generate(OrderCodeType type) {
54 CodeMeta id = new CodeMeta(); 91 CodeMeta id = new CodeMeta();
55 92
  1 +package com.yohoufo.order.service.support.codegenerator.impl;
  2 +
  3 +import lombok.Getter;
  4 +import lombok.ToString;
  5 +import org.slf4j.Logger;
  6 +import org.slf4j.LoggerFactory;
  7 +import org.springframework.stereotype.Service;
  8 +
  9 +/**
  10 + * Created by chao.chen on 2019/3/11.
  11 + */
  12 +@Service
  13 +public class SequenceStrategy {
  14 + private final static Logger logger = LoggerFactory.getLogger(SequenceStrategy.class);
  15 + public static final long DEFAULT_SEQ = 0L;
  16 +
  17 + @ToString
  18 + public static class SingleData{
  19 + @Getter
  20 + String env;
  21 + @Getter
  22 + long start;
  23 + private static SingleData data;
  24 + static SingleData create(String env, long start){
  25 + if (data == null){
  26 + synchronized (SingleData.class){
  27 + if (data == null){
  28 + data = new SingleData();
  29 + data.env = env;
  30 + data.start = start;
  31 + }
  32 + }
  33 + }
  34 + return data;
  35 + }
  36 +
  37 +
  38 + }
  39 +
  40 +
  41 + public static SingleData getStart(){
  42 + SingleData sd = SingleData.data;
  43 + logger.info("in get order code generator obtain seq Start {}", sd);
  44 + return sd;
  45 + }
  46 +
  47 +
  48 +
  49 +}
@@ -3,6 +3,7 @@ package com.yohoufo.order.service.support.codegenerator.populater; @@ -3,6 +3,7 @@ package com.yohoufo.order.service.support.codegenerator.populater;
3 3
4 import com.yohoufo.order.service.support.codegenerator.bean.CodeBitMeta; 4 import com.yohoufo.order.service.support.codegenerator.bean.CodeBitMeta;
5 import com.yohoufo.order.service.support.codegenerator.bean.CodeMeta; 5 import com.yohoufo.order.service.support.codegenerator.bean.CodeMeta;
  6 +import com.yohoufo.order.service.support.codegenerator.impl.SequenceStrategy;
6 import com.yohoufo.order.service.support.codegenerator.timer.SimpleTimer; 7 import com.yohoufo.order.service.support.codegenerator.timer.SimpleTimer;
7 8
8 import java.util.concurrent.atomic.AtomicReference; 9 import java.util.concurrent.atomic.AtomicReference;
@@ -12,15 +13,25 @@ import java.util.concurrent.atomic.AtomicReference; @@ -12,15 +13,25 @@ import java.util.concurrent.atomic.AtomicReference;
12 */ 13 */
13 public class AtomicIdPopulator implements IdPopulator { 14 public class AtomicIdPopulator implements IdPopulator {
14 15
15 - class Variant {  
16 - private long sequence = 0; 16 + public class Variant {
  17 + private long sequence = SequenceStrategy.DEFAULT_SEQ;
17 private long lastTimestamp = -1; 18 private long lastTimestamp = -1;
  19 +
  20 + public Variant(long sequence) {
  21 + this.sequence = sequence;
  22 + }
18 } 23 }
19 24
20 - private AtomicReference<Variant> variant = new AtomicReference<Variant>(new Variant()); 25 + private AtomicReference<Variant> variant;
21 26
22 public AtomicIdPopulator() { 27 public AtomicIdPopulator() {
23 super(); 28 super();
  29 + variant = new AtomicReference<Variant>(new Variant(SequenceStrategy.DEFAULT_SEQ));
  30 + }
  31 +
  32 + public AtomicIdPopulator(Variant variant) {
  33 + super();
  34 + this.variant = new AtomicReference<Variant>(variant==null ? new Variant(SequenceStrategy.DEFAULT_SEQ) : variant) ;
24 } 35 }
25 36
26 public void populateId(SimpleTimer timer, CodeMeta id, CodeBitMeta idBitMeta) { 37 public void populateId(SimpleTimer timer, CodeMeta id, CodeBitMeta idBitMeta) {
@@ -45,22 +56,31 @@ public class AtomicIdPopulator implements IdPopulator { @@ -45,22 +56,31 @@ public class AtomicIdPopulator implements IdPopulator {
45 timestamp = timer.tillNextTimeUnit(varOld.lastTimestamp); 56 timestamp = timer.tillNextTimeUnit(varOld.lastTimestamp);
46 } 57 }
47 } else { 58 } else {
48 - sequence = 0; 59 + sequence = getSeqStart();
49 } 60 }
50 61
51 // Assign the current variant by the atomic tools 62 // Assign the current variant by the atomic tools
52 - varNew = new Variant();  
53 - varNew.sequence = sequence; 63 + varNew = new Variant(sequence);
  64 + //varNew.sequence = sequence;
54 varNew.lastTimestamp = timestamp; 65 varNew.lastTimestamp = timestamp;
55 66
56 if (variant.compareAndSet(varOld, varNew)) { 67 if (variant.compareAndSet(varOld, varNew)) {
57 id.setSeq(sequence); 68 id.setSeq(sequence);
58 id.setTime(timestamp); 69 id.setTime(timestamp);
59 -  
60 break; 70 break;
61 } 71 }
62 72
63 } 73 }
64 } 74 }
65 75
  76 +
  77 + public long getSeqStart(){
  78 + long sequence = SequenceStrategy.DEFAULT_SEQ;
  79 + SequenceStrategy.SingleData sssd = SequenceStrategy.getStart();
  80 + if (sssd!=null){
  81 + sequence = sssd.getStart();
  82 + }
  83 + return sequence;
  84 + }
  85 +
66 } 86 }