自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

高可用高性能可擴(kuò)展的單號(hào)生成方案

開(kāi)發(fā) 開(kāi)發(fā)工具
在業(yè)務(wù)開(kāi)發(fā)中經(jīng)常會(huì)遇到各種單號(hào)生成,另外有多少業(yè)務(wù)量就會(huì)至少有多少的單號(hào)生成需求,所以單號(hào)生成必須高可用,必須高性能。 另外業(yè)務(wù)不同需要的單號(hào)規(guī)則可能也不相同, 所以單號(hào)服務(wù)還必須具備足夠的擴(kuò)展性。

在業(yè)務(wù)開(kāi)發(fā)中經(jīng)常會(huì)遇到各種單號(hào)生成, 例如快遞單號(hào)、服務(wù)單號(hào)、訂單號(hào)等等。 這些單號(hào)生成往往是業(yè)務(wù)邏輯處理的第一步, 單號(hào)生成出問(wèn)題,必然導(dǎo)致業(yè)務(wù)走不下去;另外有多少業(yè)務(wù)量就會(huì)至少有多少的單號(hào)生成需求。所以單號(hào)生成必須高可用,必須高性能。 另外業(yè)務(wù)不同需要的單號(hào)規(guī)則可能也不相同, 所以單號(hào)服務(wù)還必須具備足夠的擴(kuò)展性。

一、單號(hào)定義

在進(jìn)入正題之前我們先給單號(hào)下個(gè)定義, 看幾個(gè)常見(jiàn)的單號(hào)形式。

單號(hào)是一個(gè)數(shù)字和字符組成的序列, 它要滿足兩個(gè)條件: 一個(gè)是唯一, 保證唯一才可以作為業(yè)務(wù)標(biāo)識(shí); 另一個(gè)是符合業(yè)務(wù)需要的規(guī)則。 例如下面三個(gè)單號(hào):

  • 2017030400001 這個(gè)單號(hào)由兩個(gè)部分序列號(hào)日期20170304+定長(zhǎng)5位補(bǔ)0數(shù)字00001。
  • 010-6541-00001 此單號(hào)分三部分, 中間用減號(hào)連接, 第一部分為區(qū)號(hào), 第二部分為作業(yè)單位號(hào)碼, 第三部分為作業(yè)單位產(chǎn)生作業(yè)的序號(hào)。
  • QJ000001 則是由字符QJ開(kāi)頭后面跟隨數(shù)字序列的單號(hào)。

二、單號(hào)數(shù)字序列部分的生成

上述單號(hào)定義中的數(shù)字部分通常是一個(gè)自增的數(shù)字序列。 我們可以通過(guò)數(shù)據(jù)庫(kù)的自增列、 數(shù)據(jù)庫(kù)的列+1方式、 redis或者memcached的INCR指令來(lái)生成這種數(shù)字的序列。 這四種方式都可以生成序列, 但各自有各自的好處。

1. 數(shù)據(jù)庫(kù)自增列的方式

是通過(guò)數(shù)據(jù)庫(kù)的內(nèi)部機(jī)制生成的, 在普通PC上每秒約可以生成4000個(gè)數(shù)字序列, 它的好處是每一個(gè)數(shù)字序列都會(huì)保留一條記錄, 記錄生成使用時(shí)間, 缺點(diǎn)是吞吐量一般, 會(huì)占用一定的數(shù)據(jù)庫(kù)資源, 如下是一種推薦的表結(jié)構(gòu):

  1. CREATE TABLE `xx_code_sequence` ( 
  2.    `id` bigint(20) NOT NULL AUTO_INCREMENT, 
  3.    `generate_time` timestamp NOT NULL 
  4.       default CURRENT_TIMESTAMP, 
  5.    PRIMARY KEY (`id`) 
  6. ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULTCHARSET=utf8

此表有兩列, id列為bigint類型的自增長(zhǎng)字段,作為數(shù)字序列的值, generate_time時(shí)間戳字段可以記錄每一個(gè)單號(hào)的生成時(shí)間。生成數(shù)字序列的方式用sql說(shuō)明如下:

  1. begin trans; 
  2. insert into `xx_code_sequence`(generate_time)values(current_timestamp); 
  3. select last_insert_id(); 
  4. commit; 

說(shuō)明:

  • 表名格式xx_code_sequence,sto_code_0分為三部分sto為ownerKey, code固定不變,0表示表的序號(hào),可以有多個(gè)下標(biāo)不同表來(lái)支持更高的并發(fā),共有幾個(gè)表需要在開(kāi)始確認(rèn)了,確認(rèn)的依據(jù)是需要滿足的并發(fā)請(qǐng)求。表的個(gè)數(shù)必須是2的n次方,例如1, 2, 4, 8,16;
  • `id` 即序列的部分值,是通過(guò)mysql的自增特性生成的,最終的序列值是id和表序號(hào)共同組成的,假定有4個(gè)表,序號(hào)分別為0,1,2,3;那么序列值為 id<< 2 | table_index; 即id向左移位2位(移位幾位取決于表的個(gè)數(shù)),然后和表序號(hào)求或;
  • `generate_time` 為id生成時(shí)間,無(wú)其他含義。

不同序號(hào)的表可以建在不同的數(shù)據(jù)庫(kù)上,當(dāng)某個(gè)序號(hào)的表不可用時(shí)要報(bào)警,并切換到其他表上生成數(shù)字序列。

2. 數(shù)據(jù)庫(kù)的列+1方式

通過(guò)對(duì)數(shù)據(jù)庫(kù)的某列做+1操作, 來(lái)得到唯一的數(shù)字序列, 是通過(guò)數(shù)據(jù)庫(kù)的行鎖來(lái)保障唯一的, 因?yàn)樯婕暗叫墟i, 所以這種方式生成序列的單行吞吐量不會(huì)太大, 適合需要生成多種(每一種放到一行)不同數(shù)字生成需求。 如下是一種推薦的表結(jié)構(gòu):

  1. create table `xx_rowbased_sequence` ( 
  2.    `owner_key` varchar(32) NOT NULL, 
  3.    `current_value` bigint NOT NULL, 
  4.    PRIMARY KEY (`owner_key`) 
  5. ); 

表中的ownerKey列為單號(hào)種類標(biāo)識(shí), current_value為+1操作列。生成序列的方式用sql說(shuō)明如下

  1. begin trans; 
  2. UPDATE  `xx_rowbased_sequence`SET current_valuecurrent_value=current_value+1 WHERE owner_key=’order-no’; 
  3. SELECT current_value FROM `xx_rowbased_sequence` WHERE owner_key=’order-no’; 
  4. commit; 

需要注意使用此方式生成數(shù)字序列事務(wù)隔離級(jí)別需要是RR。

3. 使用redis/memcached的INCR指令方式

redis/memcached本身可以保證生成數(shù)字的唯一性,和高性能。 單一redis服務(wù)器每秒可以生成約6w左右的數(shù)字序列。 但需要注意redis必須配置主從和存儲(chǔ), 以避免在極端情況下redis節(jié)點(diǎn)down機(jī), 導(dǎo)致丟失序列或序列重復(fù)。

三、高可用實(shí)現(xiàn)

上面介紹了4種生成數(shù)字序列的方式, 但要保證高可用, 單靠一種序列生成方式還是不夠的, 我們還需要一種高可用的實(shí)現(xiàn)。

高可用數(shù)字序列生成器內(nèi)部是2的n次方個(gè)底層數(shù)字序列生成器, 每個(gè)底層序列生成器對(duì)應(yīng)一個(gè)下標(biāo)值, 下標(biāo)值的范圍為[0, 2n-1]。 在生成序列時(shí), 輪詢底層生成器, 如果正常, 則將生成結(jié)果向左移n位, 并與當(dāng)前底層序列生成器下標(biāo)取或得到最終序列值。 如果底層序列生成器發(fā)生異常, 則將其標(biāo)記為不可用, 并輪詢下一個(gè)底層序列生成器, 直到成功。

高可用實(shí)現(xiàn)類com.jd.coo.sa.sequence.ha.BitwiseLoadBalanceSequenceGen,其內(nèi)部有x個(gè)底層SequenceGen實(shí)現(xiàn),此類會(huì)輪詢的調(diào)用底層SequenceGen來(lái)生成序列,如果某個(gè)底層序列生成出錯(cuò),會(huì)從可用列表中移除掉,被移除掉的底層SequenceGen在過(guò)xx時(shí)間(默認(rèn)為5分鐘)后,可以重新加入到可用列表中。如果內(nèi)部序列生成單個(gè)序列時(shí)間超時(shí),并在最近n時(shí)間內(nèi)連續(xù)超時(shí)x次,會(huì)被移動(dòng)到異常列表,在異常列表中時(shí)間超過(guò)xx時(shí)間后,也會(huì)被重新放入可用列表中。

如果一個(gè)底層序列被標(biāo)記為不可用, 過(guò)配置時(shí)間后會(huì)將其恢復(fù)到可用列表中, 自動(dòng)恢復(fù)機(jī)制可以避免底層序列生成器已恢復(fù)可用, 而程序卻一直不使用此底層序列生成器的情況。

高可用實(shí)現(xiàn)的內(nèi)部結(jié)構(gòu)圖, 如下圖所示:

高可用實(shí)現(xiàn)的內(nèi)部結(jié)構(gòu)圖

其核心方法如下所示:

  1. public long gen(String ownerKey){ 
  2.     long sequence=0
  3.     int currentPartitionIndex=-1; 
  4.     SequenceGen innerGen=null
  5.     do{ 
  6.         long startTime=System.currentTimeMillis(); 
  7.         boolean hasError=false
  8.         try{ 
  9.             currentPartitionIndex=getCurrentPartitionIndex(ownerKey); 
  10.             LOGGER.trace("current partition index {}",currentPartitionIndex); 
  11.             innerGen=innerSequences.get(currentPartitionIndex); 
  12.             if(innerGen==SkipSequence.INSTANCE){ 
  13.                 LOGGER.warn("current partition index {} is skipped",currentPartitionIndex); 
  14.                 if(availablePartitionIndices.contains(currentPartitionIndex)){ 
  15.                     LOGGER.warn("current partition index {} is skipped, remove it",currentPartitionIndex); 
  16.                     availablePartitionIndices.remove(Integer.valueOf(currentPartitionIndex)); 
  17.                 } 
  18.  
  19.                 continue; 
  20.             } 
  21.  
  22.             HighAvailablePartitionHolder.setPartition(currentPartitionIndex); 
  23.             sequence=innerGen.gen(ownerKey); 
  24.             onGenNewId(ownerKey,currentPartitionIndex,sequence); 
  25.             LOGGER.trace("genNewId {} with inner {}",sequence,currentPartitionIndex); 
  26.             break; 
  27.         }catch(SequenceOutOfRangeException ex){ 
  28.             LOGGER.error("gen error SequenceOutOfRangeException index {} total available {}", 
  29.                     currentPartitionIndex, 
  30.                     availablePartitionIndices.size()); 
  31.             hasError=true
  32.  
  33.             LOGGER.error("set {} to SKIP",currentPartitionIndex); 
  34.             this.innerSequences.set(currentPartitionIndex,SkipSequence.INSTANCE); 
  35.             onError(ownerKey,currentPartitionIndex,innerGen,ex); 
  36.             LOGGER.error("after onError total available {}/{}",currentPartitionIndex, 
  37.                     availablePartitionIndices.size()); 
  38.  
  39.         }catch(Exception ex){ 
  40.             LOGGER.error("gen error index {} total available {}",currentPartitionIndex, 
  41.                     availablePartitionIndices.size()); 
  42.             LOGGER.error("gen error ",ex); 
  43.             hasError=true
  44.             onError(ownerKey,currentPartitionIndex,innerGen,ex); 
  45.             LOGGER.error("after onError total available {}/{}",currentPartitionIndex, 
  46.                     availablePartitionIndices.size()); 
  47.         }finally{ 
  48.             long usedTime=System.currentTimeMillis()-startTime; 
  49.             boolean isTimeout=usedTime>timeoutThresholdInMilliseconds; 
  50.             if(!hasError&&isTimeout){ 
  51.                 onTimeout(currentPartitionIndex,innerGen,usedTime); 
  52.             } 
  53.             LOGGER.trace("gen usedTime {}",usedTime); 
  54.         } 
  55.     }while(true); 
  56.     return sequence; 

使用時(shí)配置bean使用即可, 如下spring bean xml配置:

  1. <bean id="highAvailableSequenceGen" class="com.jd.coo.sa.sequence.ha.BitwiseLoadBalanceSequenceGen"> 
  2.       <!-- 指定高可用序列底層序列生成序列后向左移位位數(shù)--> 
  3.     <constructor-arg index="0" value="2"/> 
  4.      <!-- 指定底層序列 --> 
  5.     <constructor-arg index="1"> 
  6.         <map> 
  7.             <!-- key 為底層序列生成值左移位后或的下標(biāo)--> 
  8.         <entry key="0"> 
  9.                 <bean class="com.jd.coo.sa.sequence.AutoIncrementTablesSequenceGen"> 
  10.                     <property name="dataSource" ref="dataSourceA"/> 
  11.                     <property name="sequenceTableFormat" value="%s_code_%d"/> 
  12.                 </bean> 
  13.             </entry> 
  14.             <entry key="1"> 
  15.                 <bean class="com.jd.coo.sa.sequence.AutoIncrementTablesSequenceGen"> 
  16.                     <property name="dataSource" ref="dataSourceB"/> 
  17.                     <property name="sequenceTableFormat" value="%s_code_%d"/> 
  18.                 </bean> 
  19.             </entry> 
  20.             <entry key="2"> 
  21.                 <bean class="com.jd.coo.sa.sequence.AutoIncrementTablesSequenceGen"> 
  22.                     <property name="dataSource" ref="dataSourceA"/> 
  23.                     <property name="sequenceTableFormat" value="%s_code_%d"/> 
  24.                 </bean> 
  25.             </entry> 
  26.             <entry key="3"> 
  27.                 <bean class="com.jd.coo.sa.sequence.AutoIncrementTablesSequenceGen"> 
  28.                     <property name="dataSource" ref="dataSourceB"/> 
  29.                     <property name="sequenceTableFormat" value="%s_code_%d"/> 
  30.                 </bean> 
  31.             </entry> 
  32.         </map> 
  33.     </constructor-arg> 
  34.     <!-- 將timeout判斷的閾值設(shè)置為一個(gè)很大的值, 避免timeout應(yīng)用error的情況發(fā)生--> 
  35.    <property name="timeoutThresholdInMilliseconds" value="200"/> 
  36.     <!-- 超時(shí)多少次后會(huì)移出可用列表 --> 
  37.    <property name="timeoutEventCountThreshold" value="3"/> 
  38.     <!-- 計(jì)算超時(shí)異常的時(shí)間周期, 以秒為單位 --> 
  39.    <property name="timeoutTimeThresholdInSeconds" value="60" /> 
  40.     <!-- 移到不可用隊(duì)列多長(zhǎng)時(shí)間后會(huì)被重新放入可用隊(duì)列 --> 
  41.    <property name="onErrorRescueThresholdInSeconds" value="2000"/> 
  42. </bean> 

四、高性能實(shí)現(xiàn)

單號(hào)生成只是業(yè)務(wù)操作的第一個(gè)步驟, 業(yè)務(wù)操作往往是復(fù)雜耗時(shí)的, 我們必須保證單號(hào)生成的性能, 使其幾乎不會(huì)影響業(yè)務(wù)時(shí)間。

上述介紹的四種序列生成方式都是跨網(wǎng)絡(luò)通過(guò)中間件獲得的序列號(hào),要進(jìn)一步優(yōu)化其性能,我們需要將序列放在離CPU更近的地方――內(nèi)存中。我們使用如下兩種方式將數(shù)字序列放到CPU更近的地方:

  • 將內(nèi)部序列值向左移位n位, 然后序列的最右n位在內(nèi)存生成,一次生成2的n次方個(gè)數(shù)字序列, 然后放在內(nèi)存隊(duì)列中;
  • 異步提前生成:實(shí)時(shí)計(jì)算序列號(hào)方法被調(diào)用的速度, 然后在異步線程(池)中生成最近x ms需要的序列,放入內(nèi)存隊(duì)列中備用

這兩種方式并不一定都需要, 置放入內(nèi)存隊(duì)列中的數(shù)字序列越多,重啟時(shí)丟失的也會(huì)越多。

其內(nèi)部結(jié)構(gòu)圖示如下:

高性能序列使用的bean配置如下:

  1. <bean class="com.jd.coo.sa.sequence.QueuedSequenceGen" id="queuedSequenceGen" init-method="start" destroy-method="stop"> 
  2.     <!-- 指定內(nèi)部序列, 通常是一個(gè)高可用的內(nèi)部序列--> 
  3.     <constructor-arg index="0" ref="haSequenceGen" /> 
  4.     <!-- 指定內(nèi)存中生成的bit位數(shù)--> 
  5.     <property name="memoryBitLength" value="3"/> 
  6.     <!--異步生成配置--> 
  7.     <property name="enableAsync" value="true"/> 
  8.     <property name="asyncTask"> 
  9.         <bean class="com.jd.coo.sa.sequence.QueuedSequenceGen$AsyncTask"> 
  10.             <constructor-arg index="0" ref="queuedSequenceGen"/> 
  11.             <property name="loopSleepInterval" value="20"/> 
  12.             <property name="reserveTimeInMilliseconds" value="10"/> 
  13.         </bean> 
  14.     </property> 
  15.     <!--結(jié)束異步配置--> 
  16. </bean> 

通過(guò)設(shè)定memoryBitLength,指定序列的最右的memoryBitLength位在內(nèi)存中生成以提高生成的效率。 需要注意memoryBitLength值越大則在內(nèi)存中的序列條數(shù)越多, 性能越高, 如果發(fā)生重啟時(shí)丟失的序列也會(huì)越多, 要根據(jù)情況來(lái)設(shè)置。 支持異步生成序列值, 異步生成的速度會(huì)根據(jù)序列值消費(fèi)速度自適應(yīng)。

五、關(guān)于可擴(kuò)展性

單號(hào)規(guī)則多種多樣, 不能每增加一種規(guī)則就增加一個(gè)需求, 我們需要相對(duì)靈活的擴(kuò)展性。 上述介紹了多種單號(hào)數(shù)字序列的生成方式, 和數(shù)字序列生成的高可用和高性能實(shí)現(xiàn), 他們都實(shí)現(xiàn)了同一個(gè)接口:

  1. /** 
  2.  * 根據(jù)序列業(yè)務(wù)類型生成新序列的接口 
  3.  * 
  4.  * 生成序列是大致遞增的 
  5.  * 
  6.  * Created by zhaoyukai on 2016/8/8. 
  7.  */ 
  8. public interface SequenceGen { 
  9.     /** 
  10.      * 生成序列 
  11.      * @param ownerKey 序列業(yè)務(wù)key 
  12.      * @return 新序列值 
  13.      */ 
  14.     long gen(String ownerKey); 

有了這個(gè)統(tǒng)一的數(shù)字序列生成接口, 我們可以擴(kuò)展多種不同的數(shù)字序列生成方式。 或者實(shí)現(xiàn)不同的高可用、高性能機(jī)制。

另外在本文的開(kāi)頭我們介紹了多種不同的單號(hào)生成規(guī)則, 要靈活滿足這些不同的規(guī)則, 我們使用表達(dá)式來(lái)表達(dá)單號(hào)的組合規(guī)則, 通過(guò)將表達(dá)式解析成不同的Expression來(lái)實(shí)現(xiàn)不同單號(hào)部分的生成。 下面我們看一個(gè)單號(hào)表達(dá)式的示例, 如下是一個(gè)spring bean配置:

  1. <!-- 單號(hào)生成bean, 在應(yīng)用中注入此bean生成單號(hào) --> 
  2. <bean class="com.jd.coo.sa.sn.SmartSNGen" name="snGen"> 
  3.     <!-- 序列號(hào)的表達(dá)式, 見(jiàn)下面說(shuō)明 --> 
  4.     <constructor-arg value="@{ownerKey, value=SN}-@{bean, ref=sequence}-@{com.jd.coo.sa.sn.expression.CheckSumExpression}"/> 
  5.     <!-- 表達(dá)式解析器 --> 
  6.     <property name="interpreter"> 
  7.         <!-- 單號(hào)生成器的表達(dá)式解釋器, 固定為SmartInterpreter--> 
  8.         <bean class="com.jd.coo.sa.sn.expression.SmartInterpreter" name="smartInterpreter"/> 
  9.     </property> 
  10. </bean> 

SmartSNGen類負(fù)責(zé)根據(jù)表達(dá)式生成不同規(guī)則的單號(hào),其構(gòu)造函數(shù)第一個(gè)參數(shù)值:

 

  1. @{ownerKey, value=SN}-@{bean, ref=sequence}- 

@{com.jd.coo.sa.sn.expression.CheckSumExpression} 即為表達(dá)式, 該表達(dá)式分為五個(gè)部分:

  • @{ownerKey, value=SN} 在表達(dá)式生成的上下文中寫入key為ownerKey值為SN的參數(shù)
  • “-“ 表示靜態(tài)表達(dá)式“-”
  • @{bean, ref=sequence} 指定引用id為sequence的spring bean來(lái)生成表達(dá)式的一部分
  • “-“表示靜態(tài)表達(dá)式”-“
  • @{com.jd.coo.sa.sn.expression.CheckSumExpression} 表示要?jiǎng)?chuàng)建指定類com.jd.coo.sa.sn.expression.CheckSumExpression的實(shí)例來(lái)生成表達(dá)式的一部分

該bean的interpreter屬性指定了表達(dá)式的解釋器,該解釋器會(huì)將表達(dá)式值轉(zhuǎn)換為實(shí)現(xiàn)了Expression接口的對(duì)象,通過(guò)該對(duì)象可以計(jì)算出單號(hào)的值。

表達(dá)式解釋器查找表達(dá)式中的“@{”和“}”對(duì),將其內(nèi)部的表達(dá)式解析為動(dòng)態(tài)表達(dá)式,將其他部分的表達(dá)式解析為靜態(tài)表達(dá)式。動(dòng)態(tài)表達(dá)式分為三種類型:

  1. spring配置文件中的bean引用表達(dá)式
  2. 指定上下文參數(shù)的表達(dá)式
  3. 指定自定義類型的表達(dá)式

第3種表達(dá)式留出任意擴(kuò)展自定義表達(dá)式的擴(kuò)展點(diǎn)。

Expression接口定義如下:

  1. import com.jd.coo.sa.sn.GenContext; 
  2.  
  3. /** 
  4.  * SmartSNGen表達(dá)式接口 
  5.  * 
  6.  * Created by zhaoyukai on 2016/10/18. 
  7.  */ 
  8. public interface Expression { 
  9.     /** 
  10.      * 計(jì)算表達(dá)式的值 
  11.      * @param context 表達(dá)式計(jì)算上下文, 表達(dá)式可以根據(jù)需要將計(jì)算中間值存儲(chǔ)到上下文中, 以便在表達(dá)式之間共享數(shù)據(jù) 
  12.      * @return 表達(dá)式計(jì)算值 
  13.      */ 
  14.     Object eval(GenContext context); 
  15.  
  16.     /** 
  17.      * 計(jì)算優(yōu)先級(jí), 優(yōu)先級(jí)越高越先執(zhí)行, 如果表達(dá)式需要依賴其他表達(dá)式的值, 則要在依賴表達(dá)式計(jì)算之后執(zhí)行 
  18.      * @return 執(zhí)行順序 
  19.      */ 
  20.     ExecuteOrder executeOrder(); 
  21.  
  22.     /** 
  23.      * 該表達(dá)式的最大字符串長(zhǎng)度值 
  24.      * 
  25.      * @return 最大長(zhǎng)度值 
  26.      */ 
  27.     int maxLength(); 

通過(guò)實(shí)現(xiàn)此接口即可實(shí)現(xiàn)任何自定義的單號(hào)生成邏輯。如下是自定義的單號(hào)校驗(yàn)位生成表達(dá)式示例:

  1. public class CheckSumExpressionimplements Expression { 
  2.     public Object eval(GenContext context) { 
  3.         Long newId = (Long) context.get("sequence"); 
  4.         if (newId == null) { 
  5.             throw newRuntimeException("sequence can not be null when calculate checksum"); 
  6.         } 
  7.         return newId * 9 % 31 % 10; 
  8.     } 
  9.     public ExecuteOrder executeOrder() { 
  10.         return ExecuteOrder.AfterNormal; 
  11.     } 
  12.     public int maxLength() { 
  13.         return 1; 
  14.     } 

總結(jié)

本文提到了多種單號(hào)數(shù)字序列生成方式,還介紹了高可用、高性能以及擴(kuò)展性的實(shí)現(xiàn)方式。

 

  1. 要根據(jù)場(chǎng)景, 并發(fā)量, 單號(hào)類型數(shù)量選擇數(shù)字序列生成方式;
  2. 不要裸奔, 要使用高可用+高性能序列生成器, 保證單號(hào)生成方式的可用性和性能;
  3. 底層序列要從物理上做隔離, 否則出現(xiàn)硬件故障高可用機(jī)制也會(huì)時(shí)效;
  4. 使用了多個(gè)底層序列生成方式時(shí)生成的序列是大致自增, 不能保證完全自增, 這是設(shè)計(jì)使然, 如果要保證完全自增, 則會(huì)出現(xiàn)單點(diǎn), 在完全自增和單點(diǎn)的選擇上, 我們選擇了大致自增+非單點(diǎn);
  5. 高性能序列生成的性能可以通過(guò)調(diào)節(jié)其memoryBitLength屬性來(lái)提高, 但要根據(jù)業(yè)務(wù)實(shí)際情況來(lái)做選擇,memoryBitLength屬性值越高在內(nèi)存生成的序列數(shù)越多,性能越高, 但在進(jìn)程停止時(shí)丟失的序列也會(huì)越多。

作者:趙玉開(kāi),十年以上互聯(lián)網(wǎng)研發(fā)經(jīng)驗(yàn),2013年加入京東,在運(yùn)營(yíng)研發(fā)部任架構(gòu)師,期間先后主持了物流系統(tǒng)自動(dòng)化運(yùn)維平臺(tái)、青龍數(shù)據(jù)監(jiān)控系統(tǒng)和物流開(kāi)放平臺(tái)的研發(fā)工作,具有豐富的物流系統(tǒng)業(yè)務(wù)和架構(gòu)經(jīng)驗(yàn)。在此之前在和訊網(wǎng)負(fù)責(zé)股票基金行情系統(tǒng)的研發(fā)工作,具備高并發(fā)、高可用互聯(lián)網(wǎng)應(yīng)用研發(fā)經(jīng)驗(yàn)。

【本文來(lái)自51CTO專欄作者張開(kāi)濤的微信公眾號(hào)(開(kāi)濤的博客),公眾號(hào)id: kaitao-1234567】

 戳這里,看該作者更多好文

責(zé)任編輯:趙寧寧 來(lái)源: 51CTO專欄
相關(guān)推薦

2021-05-24 09:28:41

軟件開(kāi)發(fā) 技術(shù)

2017-11-27 09:14:29

2012-06-13 02:10:46

Java并發(fā)

2012-07-19 10:59:18

Jav并發(fā)

2012-11-14 15:25:58

2022-06-02 12:56:25

容器網(wǎng)絡(luò)云原生

2020-12-09 09:21:41

微服務(wù)架構(gòu)數(shù)據(jù)

2011-10-20 15:36:36

高可用高性能MySQL

2017-12-22 09:21:02

API架構(gòu)實(shí)踐

2023-03-21 08:01:44

Crimson硬件CPU

2018-03-26 09:02:54

MongoDB高可用架構(gòu)

2019-08-23 08:09:18

訂單號(hào)生成數(shù)據(jù)庫(kù)ID

2012-04-17 16:48:43

應(yīng)用優(yōu)化負(fù)載均衡Array APV

2013-03-13 10:08:17

用友UAP高可用高性能

2013-06-07 11:30:32

2013-04-09 10:16:28

OpenStackGrizzlyHyper-V

2019-03-01 11:03:22

Lustre高性能計(jì)算

2023-08-22 13:16:00

分布式數(shù)據(jù)庫(kù)架構(gòu)數(shù)據(jù)存儲(chǔ)

2022-09-29 15:24:15

MySQL數(shù)據(jù)庫(kù)高可用

2021-07-01 06:58:12

高并發(fā)訂單號(hào)SCM
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)