日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

一、高并發(fā)簡(jiǎn)介

在互聯(lián)網(wǎng)的業(yè)務(wù)架構(gòu)中,高并發(fā)是最難處理的業(yè)務(wù)之一,常見(jiàn)的使用場(chǎng)景:秒殺,搶購(gòu),訂票系統(tǒng);高并發(fā)的流程中需要處理的復(fù)雜問(wèn)題非常多,主要涉及下面幾個(gè)方面:

  • 流量管理,逐級(jí)承接削峰;
  • 網(wǎng)關(guān)控制,路由請(qǐng)求,接口熔斷;
  • 并發(fā)控制機(jī)制,資源加鎖;
  • 分布式架構(gòu),隔離服務(wù)和數(shù)據(jù)庫(kù);

高并發(fā)業(yè)務(wù)核心還是流量控制,控制流量下沉速度,或者控制承接流量的容器大小,多余的直接溢出,這是相對(duì)復(fù)雜的流程。其次就是多線程并發(fā)下訪問(wèn)共享資源,該流程需要加鎖機(jī)制,避免數(shù)據(jù)寫(xiě)出現(xiàn)錯(cuò)亂情況。

二、秒殺場(chǎng)景

1、預(yù)搶購(gòu)業(yè)務(wù)

活動(dòng)未正式開(kāi)始,先進(jìn)行活動(dòng)預(yù)約,先把一部分流量收集和控制起來(lái),在真正秒殺的時(shí)間點(diǎn),很多數(shù)據(jù)可能都已經(jīng)預(yù)處理好了,可以很大程度上削減系統(tǒng)的壓力。有了一定預(yù)約流量還可以提前對(duì)庫(kù)存系統(tǒng)做好準(zhǔn)備,一舉兩得。

場(chǎng)景:活動(dòng)預(yù)約,定金預(yù)約,高鐵搶票預(yù)購(gòu)。

2、分批搶購(gòu)

分批搶購(gòu)和搶購(gòu)的場(chǎng)景實(shí)現(xiàn)的機(jī)制是一致的,只是在流量上緩解了很多壓力,秒殺10W件庫(kù)存和秒殺100件庫(kù)存系統(tǒng)的抗壓不是一個(gè)級(jí)別。如果秒殺10W件庫(kù)存,系統(tǒng)至少承擔(dān)多于10W幾倍的流量沖擊,秒殺100件庫(kù)存,體系可能承擔(dān)幾百或者上千的流量就結(jié)束了。下面流量削峰會(huì)詳解這里的策略機(jī)制。

場(chǎng)景:分時(shí)段多場(chǎng)次搶購(gòu),高鐵票分批放出。

3、實(shí)時(shí)秒殺

最有難度的場(chǎng)景就是準(zhǔn)點(diǎn)實(shí)時(shí)的秒殺活動(dòng),假如10點(diǎn)整準(zhǔn)時(shí)搶1W件商品,在這個(gè)時(shí)間點(diǎn)前后會(huì)涌入高并發(fā)的流量,刷新頁(yè)面,或者請(qǐng)求搶購(gòu)的接口,這樣的場(chǎng)景處理起來(lái)是最復(fù)雜的。

  • 首先系統(tǒng)要承接住流量的涌入;
  • 頁(yè)面的不斷刷新要實(shí)時(shí)加載;
  • 高并發(fā)請(qǐng)求的流量控制加鎖等;
  • 服務(wù)隔離和數(shù)據(jù)庫(kù)設(shè)計(jì)的系統(tǒng)保護(hù);

場(chǎng)景:618準(zhǔn)點(diǎn)搶購(gòu),雙11準(zhǔn)點(diǎn)秒殺,電商促銷秒殺。

三、流量削峰

架構(gòu)設(shè)計(jì) | 高并發(fā)流量削峰,共享資源加鎖機(jī)制

 

1、Nginx代理

Nginx是一個(gè)高性能的HTTP和反向代理web服務(wù)器,經(jīng)常用在集群服務(wù)中做統(tǒng)一代理層和負(fù)載均衡策略,也可以作為一層流量控制層,提供兩種限流方式,一是控制速率,二是控制并發(fā)連接數(shù)。

基于漏桶算法,提供限制請(qǐng)求處理速率能力;限制IP的訪問(wèn)頻率,流量突然增大時(shí),超出的請(qǐng)求將被拒絕;還可以限制并發(fā)連接數(shù)。

高并發(fā)的秒殺場(chǎng)景下,經(jīng)過(guò)Nginx層的各種限制策略,可以控制流量在一個(gè)相對(duì)穩(wěn)定的狀態(tài)。

2、CDN節(jié)點(diǎn)

CDN靜態(tài)文件的代理節(jié)點(diǎn),秒殺場(chǎng)景的服務(wù)有這樣一個(gè)操作特點(diǎn),活動(dòng)倒計(jì)時(shí)開(kāi)始之前,大量的用戶會(huì)不斷的刷新頁(yè)面,這時(shí)候靜態(tài)頁(yè)面可以交給CDN層面代理,分擔(dān)數(shù)據(jù)服務(wù)接口的壓力。

CDN層面也可以做一層限流,在頁(yè)面內(nèi)置一層策略,假設(shè)有10W用戶點(diǎn)擊搶購(gòu),可以只放行1W的流量,其他的直接提示活動(dòng)結(jié)束即可,這也是常用的手段之一。

話外之意:平時(shí)參與的搶購(gòu)活動(dòng),可能你的請(qǐng)求根本沒(méi)有到達(dá)數(shù)據(jù)接口層面,就極速響應(yīng)商品已搶完,自行意會(huì)吧。

3、網(wǎng)關(guān)控制

網(wǎng)關(guān)層面處理服務(wù)接口路由,一些校驗(yàn)之外,最主要的是可以集成一些策略進(jìn)入網(wǎng)關(guān),比如經(jīng)過(guò)上述層層的流量控制之后,請(qǐng)求已經(jīng)接近核心的數(shù)據(jù)接口,這時(shí)在網(wǎng)關(guān)層面內(nèi)置一些策略控制:如果活動(dòng)是想激活老用戶,網(wǎng)關(guān)層面快速判斷用戶屬性,老用戶會(huì)放行請(qǐng)求;如果活動(dòng)的目的是拉新,則放行更多的新用戶。

經(jīng)過(guò)這些層面的控制,剩下的流量已經(jīng)不多了,后續(xù)才真正開(kāi)始執(zhí)行搶購(gòu)的數(shù)據(jù)操作。

話外之意:如果有10W人參加搶購(gòu)活動(dòng),真正下沉到底層的搶購(gòu)流量可能就1W,甚至更少,在分散到集群服務(wù)中處理。

4、并發(fā)熔斷

在分布式服務(wù)的接口中,還有最精細(xì)的一層控制,對(duì)于一個(gè)接口在單位之間內(nèi)控制請(qǐng)求處理的數(shù)量,這個(gè)基于接口的響應(yīng)時(shí)間綜合考慮,響應(yīng)越快,單位時(shí)間內(nèi)的并發(fā)量就越高,這里邏輯不難理解。

言外之意:流量經(jīng)過(guò)層層控制,數(shù)據(jù)接口層面分擔(dān)的壓力已經(jīng)不大,這時(shí)候就是面對(duì)秒殺業(yè)務(wù)中的加鎖問(wèn)題了。

四、分布式加鎖

1、悲觀鎖

機(jī)制描述

所有請(qǐng)求的線程必須在獲取鎖之后,才能執(zhí)行數(shù)據(jù)庫(kù)操作,并且基于序列化的模式,沒(méi)有獲取鎖的線程處于等待狀態(tài),并且設(shè)定重試機(jī)制,在單位時(shí)間后再次嘗試獲取鎖,或者直接返回。

過(guò)程圖解

架構(gòu)設(shè)計(jì) | 高并發(fā)流量削峰,共享資源加鎖機(jī)制

 

redis基礎(chǔ)命令

SETNX:加鎖的思路是,如果key不存在,將key設(shè)置為value如果key已存在,則 SETNX 不做任何動(dòng)作。并且可以給key設(shè)置過(guò)期時(shí)間,過(guò)期后其他線程可以繼續(xù)嘗試鎖獲取機(jī)制。

借助Redis的該命令模擬鎖的獲取動(dòng)作。

代碼實(shí)現(xiàn)

這里基于Redis實(shí)現(xiàn)的鎖獲取和釋放機(jī)制。

import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import JAVAx.annotation.Resource;
@Component
public class RedisLock {

    @Resource
    private Jedis jedis ;

    /**
     * 獲取鎖
     */
    public boolean getLock (String key,String value,long expire){
        try {
            String result = jedis.set( key, value, "nx", "ex", expire);
            return result != null;
        } catch (Exception e){
            e.printStackTrace();
        }finally {
            if (jedis != null) jedis.close();
        }
        return false ;
    }

    /**
     * 釋放鎖
     */
    public boolean unLock (String key){
        try {
            Long result = jedis.del(key);
            return result > 0 ;
        } catch (Exception e){
            e.printStackTrace();
        }finally {
            if (jedis != null) jedis.close();
        }
        return false ;
    }
}

這里基于Jedis的API實(shí)現(xiàn),這里提供一份配置文件。

@Configuration
public class RedisConfig {

    @Bean
    public JedisPoolConfig jedisPoolConfig (){
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig() ;
        jedisPoolConfig.setMaxIdle(8);
        jedisPoolConfig.setMaxTotal(20);
        return jedisPoolConfig ;
    }

    @Bean
    public JedisPool jedisPool (@Autowired JedisPoolConfig jedisPoolConfig){
        return new JedisPool(jedisPoolConfig,"127.0.0.1",6379) ;
    }

    @Bean
    public Jedis jedis (@Autowired JedisPool jedisPool){
        return jedisPool.getResource() ;
    }
}

問(wèn)題描述

在實(shí)際的系統(tǒng)運(yùn)行期間可能出現(xiàn)如下情況:線程01獲取鎖之后,進(jìn)程被掛起,后續(xù)該執(zhí)行的沒(méi)有執(zhí)行,鎖失效后,線程02又獲取鎖,在數(shù)據(jù)庫(kù)更新后,線程01恢復(fù),此時(shí)在持有鎖之后的狀態(tài),繼續(xù)執(zhí)行后就會(huì)容易導(dǎo)致數(shù)據(jù)錯(cuò)亂問(wèn)題。

這時(shí)候就需要引入鎖版本概念的,假設(shè)線程01獲取鎖版本1,如果沒(méi)有執(zhí)行,線程02獲取鎖版本2,執(zhí)行之后,通過(guò)鎖版本的比較,線程01的鎖版本過(guò)低,數(shù)據(jù)更新就會(huì)失敗。

CREATE TABLE `dl_data_lock` (
	`id` INT (11) NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
	`inventory` INT (11) DEFAULT '0' COMMENT '庫(kù)存量',
	`lock_value` INT (11) NOT NULL DEFAULT '0' COMMENT '鎖版本',
	PRIMARY KEY (`id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT = '鎖機(jī)制表';

說(shuō)明:lock_value就是記錄鎖版本,作為控制數(shù)據(jù)更新的條件。

<update id="updateByLock">
    UPDATE dl_data_lock SET inventory=inventory-1,lock_value=#{lockVersion}
    WHERE id=#{id} AND lock_value <#{lockVersion}
</update>

說(shuō)明:這里的更新操作,不但要求線程獲取鎖,還會(huì)判斷線程鎖的版本不能低于當(dāng)前更新記錄中的最新鎖版本。

2、樂(lè)觀鎖

機(jī)制描述

樂(lè)觀鎖大多是基于數(shù)據(jù)記錄來(lái)控制,在更新數(shù)據(jù)庫(kù)的時(shí)候,基于前置的查詢條件判斷,如果查詢出來(lái)的數(shù)據(jù)沒(méi)有被修改,則更新操作成功,如果前置的查詢結(jié)果作為更新的條件不成立,則數(shù)據(jù)寫(xiě)失敗。

過(guò)程圖解

架構(gòu)設(shè)計(jì) | 高并發(fā)流量削峰,共享資源加鎖機(jī)制

 

代碼實(shí)現(xiàn)

業(yè)務(wù)流程,先查詢要更新的記錄,然后把讀取的列,作為更新條件。

@Override
public Boolean updateByInventory(Integer id) {
    DataLockEntity dataLockEntity = dataLockMApper.getById(id);
    if (dataLockEntity != null){
        return dataLockMapper.updateByInventory(id,dataLockEntity.getInventory())>0 ;
    }
    return false ;
}

例如如果要把庫(kù)存更新,就把讀取的庫(kù)存數(shù)據(jù)作為更新條件,如果讀取庫(kù)存是100,在更新的時(shí)候庫(kù)存變了,則更新條件自然不能成立。

<update id="updateByInventory">
    UPDATE dl_data_lock SET inventory=inventory-1 WHERE id=#{id} AND inventory=#{inventory}
</update>

五、分布式服務(wù)

1、服務(wù)保護(hù)

在處理高并發(fā)的秒殺場(chǎng)景時(shí),經(jīng)常出現(xiàn)服務(wù)掛掉場(chǎng)景,常見(jiàn)某些APP的營(yíng)銷頁(yè)面,出現(xiàn)活動(dòng)火爆頁(yè)面丟失的提示情況,但是不影響整體應(yīng)用的運(yùn)行,這就是服務(wù)的隔離和保護(hù)機(jī)制。

基于分布式的服務(wù)結(jié)構(gòu)可以把高并發(fā)的業(yè)務(wù)服務(wù)獨(dú)立出來(lái),不會(huì)因?yàn)槊霘⒎?wù)掛掉影響整體的服務(wù),導(dǎo)致服務(wù)雪崩的場(chǎng)景。

2、數(shù)據(jù)庫(kù)保護(hù)

數(shù)據(jù)庫(kù)保護(hù)和服務(wù)保護(hù)是相輔相成的,分布式服務(wù)架構(gòu)下,服務(wù)和數(shù)據(jù)庫(kù)是對(duì)應(yīng)的,理論上秒殺服務(wù)對(duì)應(yīng)的就是秒殺數(shù)據(jù)庫(kù),不會(huì)因?yàn)槊霘?kù)掛掉,導(dǎo)致整個(gè)數(shù)據(jù)庫(kù)宕機(jī)。

 

分享到:
標(biāo)簽:架構(gòu) 設(shè)計(jì)
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定