主頁 > 軟體設計 > 解密秒殺系統架構:不是所有的秒殺都是秒殺

解密秒殺系統架構:不是所有的秒殺都是秒殺

2023-01-04 07:42:51 軟體設計

摘要:究竟什么樣的系統算是高并發系統?今天,我們就一起解密高并發業務場景下典型的秒殺系統的架構,

本文分享自華為云社區《【高并發】秒殺系統架構解密,不是所有的秒殺都是秒殺(升級版)!!》,作者: 冰 河,

究竟什么樣的系統算是高并發系統?今天,我們就一起解密高并發業務場景下典型的秒殺系統的架構,

電商系統架構

在電商領域,存在著典型的秒殺業務場景,那何謂秒殺場景呢,簡單的來說就是一件商品的購買人數遠遠大于這件商品的庫存,而且這件商品在很短的時間內就會被搶購一空, 比如每年的618、雙11大促,小米新品促銷等業務場景,就是典型的秒殺業務場景,

我們可以將電商系統的架構簡化成下圖所示,

由圖所示,我們可以簡單的將電商系統的核心層分為:負載均衡層、應用層和持久層,接下來,我們就預估下每一層的并發量,

  • 假如負載均衡層使用的是高性能的Nginx,則我們可以預估Nginx最大的并發度為:10W+,這里是以萬為單位,
  • 假設應用層我們使用的是Tomcat,而Tomcat的最大并發度可以預估為800左右,這里是以百為單位,
  • 假設持久層的快取使用的是Redis,資料庫使用的是MySQL,MySQL的最大并發度可以預估為1000左右,以千為單位,Redis的最大并發度可以預估為5W左右,以萬為單位,

所以,負載均衡層、應用層和持久層各自的并發度是不同的,那么,為了提升系統的總體并發度和快取,我們通常可以采取哪些方案呢?

(1)系統擴容

系統擴容包括垂直擴容和水平擴容,增加設備和機器配置,絕大多數的場景有效,

(2)快取

本地快取或者集中式快取,減少網路IO,基于記憶體讀取資料,大部分場景有效,

(3)讀寫分離

采用讀寫分離,分而治之,增加機器的并行處理能力,

秒殺系統的特點

對于秒殺系統來說,我們可以從業務和技術兩個角度來闡述其自身存在的一些特點,

秒殺系統的業務特點

這里,我們可以使用12306網站來舉例,每年春運時,12306網站的訪問量是非常大的,但是網站平時的訪問量卻是比較平緩的,也就是說,每年春運時節,12306網站的訪問量會出現瞬時突增的現象,

再比如,小米秒殺系統,在上午10點開售商品,10點前的訪問量比較平緩,10點時同樣會出現并發量瞬時突增的現象,

所以,秒殺系統的流量和并發量我們可以使用下圖來表示,

由圖可以看出,秒殺系統的并發量存在瞬時凸峰的特點,也叫做流量突刺現象,

我們可以將秒殺系統的特點總結如下,

(1)限時、限量、限價

在規定的時間內進行;秒殺活動中商品的數量有限;商品的價格會遠遠低于原來的價格,也就是說,在秒殺活動中,商品會以遠遠低于原來的價格出售,

例如,秒殺活動的時間僅限于某天上午10點到10點半,商品數量只有10萬件,售完為止,而且商品的價格非常低,例如:1元購等業務場景,

限時、限量和限價可以單獨存在,也可以組合存在,

(2)活動預熱

需要提前配置活動;活動還未開始時,用戶可以查看活動的相關資訊;秒殺活動開始前,對活動進行大力宣傳,

(3)持續時間短

購買的人數數量龐大;商品會迅速售完,

在系統流量呈現上,就會出現一個突刺現象,此時的并發訪問量是非常高的,大部分秒殺場景下,商品會在極短的時間內售完,

秒殺系統的技術特點

我們可以將秒殺系統的技術特點總結如下,

(1)瞬時并發量非常高

大量用戶會在同一時間搶購商品;瞬間并發峰值非常高,

(2)讀多寫少

系統中商品頁的訪問量巨大;商品的可購買數量非常少;庫存的查詢訪問數量遠遠大于商品的購買數量,

在商品頁中往往會加入一些限流措施,例如早期的秒殺系統商品頁會加入驗證碼來平滑前端對系統的訪問流量,近期的秒殺系統商品詳情頁會在用戶打開頁面時,提示用戶登錄系統,這都是對系統的訪問進行限流的一些措施,

(3)流程簡單

秒殺系統的業務流程一般比較簡單;總體上來說,秒殺系統的業務流程可以概括為:下單減庫存,

秒殺三階段

通常,從秒殺開始到結束,往往會經歷三個階段:

  • 準備階段:這個階段也叫作系統預熱階段,此時會提前預熱秒殺系統的業務資料,往往這個時候,用戶會不斷重繪秒殺頁面,來查看秒殺活動是否已經開始,在一定程度上,通過用戶不斷重繪頁面的操作,可以將一些資料存盤到Redis中進行預熱,
  • 秒殺階段:這個階段主要是秒殺活動的程序,會產生瞬時的高并發流量,對系統資源會造成巨大的沖擊,所以,在秒殺階段一定要做好系統防護,
  • 結算階段: 完成秒殺后的資料處理作業,比如資料的一致性問題處理,例外情況處理,商品的回倉處理等,

針對這種短時間內大流量的系統來說,就不太適合使用系統擴容了,因為即使系統擴容了,也就是在很短的時間內會使用到擴容后的系統,大部分時間內,系統無需擴容即可正常訪問, 那么,我們可以采取哪些方案來提升系統的秒殺性能呢?

秒殺系統方案

針對秒殺系統的特點,我們可以采取如下的措施來提升系統的性能,

(1)異步解耦

將整體流程進行拆解,核心流程通過佇列方式進行控制,

(2)限流防刷

控制網站整體流量,提高請求的門檻,避免系統資源耗盡,

(3)資源控制

將整體流程中的資源調度進行控制,揚長避短,

由于應用層能夠承載的并發量比快取的并發量少很多,所以,在高并發系統中,我們可以直接使用OpenResty由負載均衡層訪問快取,避免了呼叫應用層的性能損耗,大家可以到https://openresty.org/cn/來了解有關OpenResty更多的知識,同時,由于秒殺系統中,商品數量比較少,我們也可以使用動態渲染技術,CDN技術來加速網站的訪問性能,

如果在秒殺活動開始時,并發量太高時,我們可以將用戶的請求放入佇列中進行處理,并為用戶彈出排隊頁面,

注:圖片來自魅族

秒殺系統時序圖

網上很多的秒殺系統和對秒殺系統的解決方案,并不是真正的秒殺系統,他們采用的只是同步處理請求的方案,一旦并發量真的上來了,他們所謂的秒殺系統的性能會急劇下降,我們先來看一下秒殺系統在同步下單時的時序圖,

同步下單流程

1.用戶發起秒殺請求

在同步下單流程中,首先,用戶發起秒殺請求,商城服務需要依次執行如下流程來處理秒殺請求的業務,

(1)識別驗證碼是否正確

商城服務判斷用戶發起秒殺請求時提交的驗證碼是否正確,

(2)判斷活動是否已經結束

驗證當前秒殺活動是否已經結束,

(3)驗證訪問請求是否處于黑名單

在電商領域中,存在著很多的惡意競爭,也就是說,其他商家可能會通過不正當手段來惡意請求秒殺系統,占用系統大量的帶寬和其他系統資源,此時,就需要使用風控系統等實作黑名單機制,為了簡單,也可以使用攔截器統計訪問頻次實作黑名單機制,

(4)驗證真實庫存是否足夠

系統需要驗證商品的真實庫存是否足夠,是否能夠支持本次秒殺活動的商品庫存量,

(5)扣減快取中的庫存

在秒殺業務中,往往會將商品庫存等資訊存放在快取中,此時,還需要驗證秒殺活動使用的商品庫存是否足夠,并且需要扣減秒殺活動的商品庫存數量,

(6)計算秒殺的價格

由于在秒殺活動中,商品的秒殺價格和商品的真實價格存在差異,所以,需要計算商品的秒殺價格,

注意:如果在秒殺場景中,系統涉及的業務更加復雜的話,會涉及更多的業務操作,這里,我只是列舉出一些常見的業務操作,

2.提交訂單

(1)訂單入口

將用戶提交的訂單資訊保存到資料庫中,

(2)扣減真實庫存

訂單入庫后,需要在商品的真實庫存中將本次成功下單的商品數量扣除,

如果我們使用上述流程開發了一個秒殺系統,當用戶發起秒殺請求時,由于系統每個業務流程都是串行執行的,整體上系統的性能不會太高,當并發量太高時,我們會為用戶彈出下面的排隊頁面,來提示用戶進行等待,

注:圖片來自魅族

此時的排隊時間可能是15秒,也可能是30秒,甚至是更長時間,這就存在一個問題:在用戶發起秒殺請求到服務器回傳結果的這段時間內,客戶端和服務器之間的連接不會被釋放,這就會占大量占用服務器的資源,

網上很多介紹如何實作秒殺系統的文章都是采用的這種方式,那么,這種方式能做秒殺系統嗎?答案是可以做,但是這種方式支撐的并發量并不是太高,此時,有些網友可能會問:我們公司就是這樣做的秒殺系統啊!上線后一直在用,沒啥問題啊!我想說的是:使用同步下單方式確實可以做秒殺系統,但是同步下單的性能不會太高,之所以你們公司采用同步下單的方式做秒殺系統沒出現大的問題,那是因為你們的秒殺系統的并發量沒達到一定的量級,也就是說,你們的秒殺系統的并發量其實并不高,

所以,很多所謂的秒殺系統,存在著秒殺的業務,但是稱不上真正的秒殺系統,原因就在于他們使用的是同步的下單流程,限制了系統的并發流量,之所以上線后沒出現太大的問題,是因為系統的并發量不高,不足以壓死整個系統,

如果12306、淘寶、天貓、京東、小米等大型商城的秒殺系統是這么玩的話,那么,他們的系統遲早會被玩死,他們的系統工程師不被開除才怪!所以,在秒殺系統中,這種同步處理下單的業務流程的方案是不可取的,

以上就是同步下單的整個流程操作,如果下單流程更加復雜的話,就會涉及到更多的業務操作,

異步下單流程

既然同步下單流程的秒殺系統稱不上真正的秒殺系統,那我們就需要采用異步的下單流程了,異步的下單流程不會限制系統的高并發流量,

1.用戶發起秒殺請求

用戶發起秒殺請求后,商城服務會經過如下業務流程,

(1)檢測驗證碼是否正確

用戶發起秒殺請求時,會將驗證碼一同發送過來,系統會檢驗驗證碼是否有效,并且是否正確,

(2)是否限流

系統會對用戶的請求進行是否限流的判斷,這里,我們可以通過判斷訊息佇列的長度來進行判斷,因為我們將用戶的請求放在了訊息佇列中,訊息佇列中堆積的是用戶的請求,我們可以根據當前訊息佇列中存在的待處理的請求數量來判斷是否需要對用戶的請求進行限流處理,

例如,在秒殺活動中,我們出售1000件商品,此時在訊息佇列中存在1000個請求,如果后續仍然有用戶發起秒殺請求,則后續的請求我們可以不再處理,直接向用戶回傳商品已售完的提示,

所以,使用限流后,我們可以更快的處理用戶的請求和釋放連接的資源,

(3)發送MQ

用戶的秒殺請求通過前面的驗證后,我們就可以將用戶的請求引數等資訊發送到MQ中進行異步處理,同時,向用戶回應結果資訊,在商城服務中,會有專門的異步任務處理模塊來消費訊息佇列中的請求,并處理后續的異步流程,

在用戶發起秒殺請求時,異步下單流程比同步下單流程處理的業務操作更少,它將后續的操作通過MQ發送給異步處理模塊進行處理,并迅速向用戶回傳回應結果,釋放請求連接,

2.異步處理

我們可以將下單流程的如下操作進行異步處理,

(1)判斷活動是否已經結束

(2)判斷本次請求是否處于系統黑名單,為了防止電商領域同行的惡意競爭可以為系統增加黑名單機制,將惡意的請求放入系統的黑名單中,可以使用攔截器統計訪問頻次來實作,

(3)扣減快取中的秒殺商品的庫存數量,

(4)生成秒殺Token,這個Token是系結當前用戶和當前秒殺活動的,只有生成了秒殺Token的請求才有資格進行秒殺活動,

這里我們引入了異步處理機制,在異步處理中,系統使用多少資源,分配多少執行緒來處理相應的任務,是可以進行控制的,

3.短輪詢查詢秒殺結果

這里,可以采取客戶端短輪詢查詢是否獲得秒殺資格的方案,例如,客戶端可以每隔3秒鐘輪詢請求服務器,查詢是否獲得秒殺資格,這里,我們在服務器的處理就是判斷當前用戶是否存在秒殺Token,如果服務器為當前用戶生成了秒殺Token,則當前用戶存在秒殺資格,否則繼續輪詢查詢,直到超時或者服務器回傳商品已售完或者無秒殺資格等資訊為止,

采用短輪詢查詢秒殺結果時,在頁面上我們同樣可以提示用戶排隊處理中,但是此時客戶端會每隔幾秒輪詢服務器查詢秒殺資格的狀態,相比于同步下單流程來說,無需長時間占用請求連接,

此時,可能會有網友會問:采用短輪詢查詢的方式,會不會存在直到超時也查詢不到是否具有秒殺資格的狀態呢?答案是:有可能! 這里我們試想一下秒殺的真實場景,商家參加秒殺活動本質上不是為了賺錢,而是提升商品的銷量和商家的知名度,吸引更多的用戶來買自己的商品,所以,我們不必保證用戶能夠100%的查詢到是否具有秒殺資格的狀態,

4.秒殺結算

(1)驗證下單Token

客戶端提交秒殺結算時,會將秒殺Token一同提交到服務器,商城服務會驗證當前的秒殺Token是否有效,

(2)加入秒殺購物車

商城服務在驗證秒殺Token合法并有效后,會將用戶秒殺的商品添加到秒殺購物車,

5.提交訂單

(1)訂單入庫

將用戶提交的訂單資訊保存到資料庫中,

(2)洗掉Token

秒殺商品訂單入庫成功后,洗掉秒殺Token,

這里大家可以思考一個問題:我們為什么只在異步下單流程的粉色部分采用異步處理,而沒有在其他部分采取異步削峰和填谷的措施呢?

這是因為在異步下單流程的設計中,無論是在產品設計上還是在介面設計上,我們在用戶發起秒殺請求階段對用戶的請求進行了限流操作,可以說,系統的限流操作是非常前置的,在用戶發起秒殺請求時進行了限流,系統的高峰流量已經被平滑解決了,再往后走,其實系統的并發量和系統流量并不是非常高了,

所以,網上很多的文章和帖子中在介紹秒殺系統時,說是在下單時使用異步削峰來進行一些限流操作,那都是在扯淡! 因為下單操作在整個秒殺系統的流程中屬于比較靠后的操作了,限流操作一定要前置處理,在秒殺業務后面的流程中做限流操作是沒啥卵用的,

高并發“黑科技”與致勝奇招

假設,在秒殺系統中我們使用Redis實作快取,假設Redis的讀寫并發量在5萬左右,我們的商城秒殺業務需要支持的并發量在100萬左右,如果這100萬的并發全部打入Redis中,Redis很可能就會掛掉,那么,我們如何解決這個問題呢?接下來,我們就一起來探討這個問題,

在高并發的秒殺系統中,如果采用Redis快取資料,則Redis快取的并發處理能力是關鍵,因為很多的前綴操作都需要訪問Redis,而異步削峰只是基本的操作,關鍵還是要保證Redis的并發處理能力,

解決這個問題的關鍵思想就是:分而治之,將商品庫存分開放,

暗度陳倉

我們在Redis中存盤秒殺商品的庫存數量時,可以將秒殺商品的庫存進行“分割”存盤來提升Redis的讀寫并發量,

例如,原來的秒殺商品的id為10001,庫存為1000件,在Redis中的存盤為(10001, 1000),我們將原有的庫存分割為5份,則每份的庫存為200件,此時,我們在Redia中存盤的資訊為(10001_0, 200),(10001_1, 200),(10001_2, 200),(10001_3, 200),(10001_4, 200),

此時,我們將庫存進行分割后,每個分割后的庫存使用商品id加上一個數字標識來存盤,這樣,在對存盤商品庫存的每個Key進行Hash運算時,得出的Hash結果是不同的,這就說明,存盤商品庫存的Key有很大概率不在Redis的同一個槽位中,這就能夠提升Redis處理請求的性能和并發量,

分割庫存后,我們還需要在Redis中存盤一份商品id和分割庫存后的Key的映射關系,此時映射關系的Key為商品的id,也就是10001,Value為分割庫存后存盤庫存資訊的Key,也就是10001_0,10001_1,10001_2,10001_3,10001_4,在Redis中我們可以使用List來存盤這些值,

在真正處理庫存資訊時,我們可以先從Redis中查詢出秒殺商品對應的分割庫存后的所有Key,同時使用AtomicLong來記錄當前的請求數量,使用請求數量對從Redia中查詢出的秒殺商品對應的分割庫存后的所有Key的長度進行求模運算,得出的結果為0,1,2,3,4,再在前面拼接上商品id就可以得出真正的庫存快取的Key,此時,就可以根據這個Key直接到Redis中獲取相應的庫存資訊,

移花接木

在高并發業務場景中,我們可以直接使用Lua腳本庫(OpenResty)從負載均衡層直接訪問快取,

這里,我們思考一個場景:如果在秒殺業務場景中,秒殺的商品被瞬間搶購一空,此時,用戶再發起秒殺請求時,如果系統由負載均衡層請求應用層的各個服務,再由應用層的各個服務訪問快取和資料庫,其實,本質上已經沒有任何意義了,因為商品已經賣完了,再通過系統的應用層進行層層校驗已經沒有太多意義了!!而應用層的并發訪問量是以百為單位的,這又在一定程度上會降低系統的并發度,

為了解決這個問題,此時,我們可以在系統的負載均衡層取出用戶發送請求時攜帶的用戶id,商品id和秒殺活動id等資訊,直接通過Lua腳本等技術來訪問快取中的庫存資訊,如果秒殺商品的庫存小于或者等于0,則直接回傳用戶商品已售完的提示資訊,而不用再經過應用層的層層校驗了, 針對這個架構,我們可以參見本文中的電商系統的架構圖(正文開始的第一張圖),

Redis助力秒殺系統

我們可以在Redis中設計一個Hash資料結構,來支持商品庫存的扣減操作,如下所示,

seckill:goodsStock:${goodsId}{
totalCount:200,
initStatus:0,
seckillCount:0
}

在我們設計的Hash資料結構中,有三個非常主要的屬性,

  • totalCount:表示參與秒殺的商品的總數量,在秒殺活動開始前,我們就需要提前將此值加載到Redis快取中,
  • initStatus:我們把這個值設計成一個布林值,秒殺開始前,這個值為0,表示秒殺未開始,可以通過定時任務或者后臺操作,將此值修改為1,則表示秒殺開始,
  • seckillCount:表示秒殺的商品數量,在秒殺程序中,此值的上限為totalCount,當此值達到totalCount時,表示商品已經秒殺完畢,

我們可以通過下面的代碼片段在秒殺預熱階段,將要參與秒殺的商品資料加載的快取,

/**
 * @author binghe
 * @description 秒殺前構建商品快取代碼示例
 */
public class SeckillCacheBuilder{
 private static final String GOODS_CACHE = "seckill:goodsStock:"; 
 private String getCacheKey(String id) { 
 return GOODS_CACHE.concat(id);
 } 
 public void prepare(String id, int totalCount) { 
 String key = getCacheKey(id); 
 Map<String, Integer> goods = new HashMap<>(); 
 goods.put("totalCount", totalCount); 
 goods.put("initStatus", 0); 
 goods.put("seckillCount", 0); 
 redisTemplate.opsForHash().putAll(key, goods); 
 }
}

秒殺開始的時候,我們需要在代碼中首先判斷快取中的seckillCount值是否小于totalCount值,如果seckillCount值確實小于totalCount值,我們才能夠對庫存進行鎖定,在我們的程式中,這兩步其實并不是原子性的,如果在分布式環境中,我們通過多臺機器同時操作Redis快取,就會發生同步問題,進而引起“超賣”的嚴重后果,

在電商領域,有一個專業名詞叫作“超賣”,顧名思義:“超賣”就是說賣出的商品數量比商品的庫存數量多,這在電商領域是一個非常嚴重的問題,那么,我們如何解決“超賣”問題呢?

Lua腳本完美解決超賣問題

我們如何解決多臺機器同時操作Redis出現的同步問題呢?一個比較好的方案就是使用Lua腳本,我們可以使用Lua腳本將Redis中扣減庫存的操作封裝成一個原子操作,這樣就能夠保證操作的原子性,從而解決高并發環境下的同步問題,

例如,我們可以撰寫如下的Lua腳本代碼,來執行Redis中的庫存扣減操作,

local resultFlag = "0" 
local n = tonumber(ARGV[1]) 
local key = KEYS[1] 
local goodsInfo = redis.call("HMGET",key,"totalCount","seckillCount") 
local total = tonumber(goodsInfo[1]) 
local alloc = tonumber(goodsInfo[2]) 
if not total then 
 return resultFlag 
end 
if total >= alloc + n  then 
 local ret = redis.call("HINCRBY",key,"seckillCount",n) 
 return tostring(ret) 
end 
return resultFlag

我們可以使用如下的Java代碼來呼叫上述Lua腳本,

public int secKill(String id, int number) { 
 String key = getCacheKey(id); 
 Object seckillCount = redisTemplate.execute(script, Arrays.asList(key), String.valueOf(number)); 
 return Integer.valueOf(seckillCount.toString()); 
}

這樣,我們在執行秒殺活動時,就能夠保證操作的原子性,從而有效的避免資料的同步問題,進而有效的解決了“超賣”問題,

 

點擊關注,第一時間了解華為云新鮮技術~

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/541150.html

標籤:其他

上一篇:淺談研發實踐的技術債與效能提升

下一篇:淺談研發實踐的技術債與效能提升

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more