On milyon düzeyinde yüksek eşzamanlılık "spike" mimari tasarımı

Tatillerde memleketlerine dönen ve birinci ve ikinci kademe şehirlerde oynamak için dışarı çıkan insanlar neredeyse bir sorunla karşı karşıya: tren biletleri alın! Çoğu durumda biletler şu anda rezerve edilebilmesine rağmen, biletler piyasaya sürüldüğünde şu anda bilet yok. Herkese inanıyorum Hepsinin derin bir anlayışı var. Özellikle Bahar Şenliği sırasında herkes sadece 12306 kullanmakla kalmıyor, aynı zamanda "Zhixing" ve diğer bilet kapma yazılımlarını da düşünüyor.Bu dönemde ülke çapında yüz milyonlarca insan bilet için yarışıyor. "12306 hizmeti", dünyadaki hiçbir spike sisteminin geçemeyeceği QPS'yi taşır ve milyonlarca eşzamanlılık normal olamaz! Yazar, "12306" nın sunucu tarafı mimarisini inceledi ve sistem tasarımının birçok önemli noktasını öğrendi. Burada sizinle paylaşacağım ve bir örneği simüle edeceğim: 1 milyon kişi aynı anda 10.000 tren bileti aldığında normal ve istikrarlı hizmet nasıl sağlanır.

github kaynak adresi:

https://github.com/GuoZhaoran/spikeSystem

1. Büyük ölçekli, yüksek eş zamanlı sistem mimarisi

Yüksek düzeyde eşzamanlı sistem mimarisi, dağıtılmış küme dağıtımını benimseyecektir.Hizmetin üst katmanı, katman katman yük dengeleme özelliğine sahiptir ve sistemin yüksek kullanılabilirliğini sağlamak için çeşitli felaket kurtarma yöntemleri (çift yangın motoru odası, düğüm hatası toleransı, sunucu felaket kurtarma vb.) Sağlar ve trafik, Farklı yük kapasiteleri ve yapılandırma stratejileri, farklı sunucular için dengelenmiştir. Aşağıda basit bir şematik diyagram bulunmaktadır:

1.1 Yük Dengelemeye Giriş

Yukarıdaki şekil, kullanıcı isteklerinden sunucuya giden üç katmanlı yük dengelemeyi açıklar. Üç tür yük dengeleme aşağıda kısaca açıklanmıştır:

1, OSPF (Önce En Kısa Bağlantıyı Aç) bir İç Ağ Geçidi Protokolüdür (IGP). OSPF, en kısa yol ağacını oluşturmak için yönlendiriciler arasındaki ağ arabirimlerinin durumunu duyurarak bir bağlantı durumu veritabanı oluşturur. OSPF, yönlendirme arabiriminde maliyet değerini otomatik olarak hesaplar, ancak arabirimin maliyet değerini manuel olarak da belirleyebilirsiniz. Otomatik olarak hesaplanan değer. OSPF tarafından hesaplanan Maliyet de arayüz bant genişliğiyle ters orantılıdır. Bant genişliği ne kadar yüksekse Maliyet değeri o kadar düşük olur. Hedefle aynı Maliyet değerine sahip yollar için yük dengeleme gerçekleştirilebilir ve aynı anda 6 bağlantıya kadar yük dengeleme gerçekleştirilebilir.

2, LVS (Linux VirtualServer), IP yük dengeleme teknolojisi ve içerik tabanlı istek dağıtım teknolojisini kullanan bir küme (Küme) teknolojisidir. Programlayıcı iyi bir aktarım hızına sahiptir, istekleri farklı sunuculara dengeli bir şekilde aktarır ve programlayıcı, sunucu arızalarını otomatik olarak korur, böylece yüksek performanslı, yüksek kullanılabilirliğe sahip bir sanal sunucuya bir sunucu grubu oluşturur.

3. Nginx herkese aşina olmalı, çok yüksek performanslı bir http proxy / ters proxy sunucusudur ve genellikle hizmet geliştirmede yük dengeleme için kullanılır. Nginx'in yük dengelemeye ulaşmasının üç ana yolu vardır: round-robin, ağırlıklı round-robin ve ip hash round-robin. Aşağıda, Nginx ağırlıklı round-robin için özel yapılandırma ve testler yapacağız.

1.2 Nginx ağırlıklı anket gösterimi

Nginx, ağırlıklı round-robin yapılandırmasının ilgili hizmete bir ağırlık değeri ekleyebildiği yukarı akış modülü aracılığıyla yük dengelemesini gerçekleştirir.Konfigürasyon sırasında, karşılık gelen yük sunucunun performansına ve yük kapasitesine göre ayarlanabilir. Aşağıda, ağırlıklı bir yoklama yükü yapılandırması yer almaktadır. 3001-3004 numaralı bağlantı noktasını yerel olarak izleyeceğim ve sırasıyla 1, 2, 3 ve 4 ağırlıklarını yapılandıracağım:

# Yük dengeleme yükünü dengelemeyi yapılandırın yük_rule {server 127.0.0.1:3001 weight = 1; server 127.0.0.1:3002 weight = 2; server 127.0.0.1:3003 weight = 3; server 127.0.0.1:3004 weight = 4;} .. . sunucu {listen 80; server_name load_balance.com www.load_balance.com; location / {proxy_pass http: // load_rule;}}

Yerel / etc / hosts dizininde www.load_balance.com sanal etki alanı adı adresini yapılandırdım ve ardından dört http bağlantı noktası izleme hizmetini açmak için Go dilini kullandım, aşağıdaki 3001 numaralı bağlantı noktasını dinleyen Go programı, diğer birkaçının yalnızca değiştirilmesi gerekiyor Bağlantı noktası şunlar olabilir:

paket mainimport ("net / http" "os" "dizeler") func main () {http.HandleFunc ("/ buy / ticket", handleReq) http.ListenAndServe (": 3001", nil)} // İstek işlevi işleniyor , İsteğe göre, yanıt sonucu bilgilerini log func handleReq'e yazın (w http.ResponseWriter, r * http.Request) {failMsg: = "handle in port:" writeLog (failMsg, "./stat.log")}//write Log func writeLog (msg string, logPath string) {fd, _: = os.OpenFile (logPath, os.O_RDWR | os.O_CREATE | os.O_APPEND, 0644) defer fd.Close () içerik: = strings.Join ( string {msg, "\ r \ n"}, "3001") buf: = bayt (içerik) fd.Write (buf)}

İstenen bağlantı noktası günlüğü bilgilerini ./stat.log dosyasına yazdım ve ardından basınç ölçümü gerçekleştirmek için ab basınç ölçüm aracını kullandım:

ab -n 1000 -c 100

İstatistik günlüğündeki sonuçlara göre, 3001-3004 portları sırasıyla 100, 200, 300 ve 400 istek aldı, bunlar nginx'te yapılandırdığım ağırlık oranı ile iyi bir uyum içinde ve yük sonrası trafik çok yüksek Düzgün ve rastgele. Spesifik uygulama için, nginx'in upsteam modülünün kaynak koduna başvurabilirsiniz.İşte önerilen bir makale: Nginx'te yukarı akış mekanizmasının yük dengelemesi

2. Çivi çakma sisteminin seçimi

Başlangıçta bahsettiğimiz soruya geri dönelim: Tren bileti spike sistemi yüksek eşzamanlılık altında normal ve istikrarlı hizmetleri nasıl sağlıyor?

Yukarıdaki girişten, kullanıcı ani trafiğinin katman katman yük dengeleme yoluyla farklı sunuculara eşit olarak dağıtıldığını biliyoruz.Öyle olsa bile, kümedeki tek bir makinenin QPS'si de çok yüksek. Tek bir makinenin performansı en uç noktaya nasıl optimize edilir? Bu sorunu çözmek için bir şeyi anlamalıyız: Bilet rezervasyon sistemi genellikle sipariş oluşturma, envanter kesintisi ve kullanıcı ödemesinin üç temel aşamasını ele almak zorundadır.Sistemimizin yapması gereken, tren bileti siparişlerini garanti etmektir. Fazla satma, çok sat , Satılan her biletin geçerli olması için ödenmesi ve sistemin son derece yüksek eşzamanlılığa dayanması garanti edilmesi gerekir. Bu üç aşamanın sırasını daha makul hale getirmek için nasıl değiştirebiliriz? Şimdi analiz edelim:

2.1 Envanteri azaltma emri

Eşzamanlı kullanıcı istekleri sunucuya ulaştığında, önce bir sipariş oluşturulur, ardından envanter çıkarılır ve kullanıcı ödeme için bekler. Bu sipariş, çoğu insanın aklına gelen ilk çözümdür.Bu durumda, sipariş oluşturulduktan sonra envanter azalacağı için siparişin fazla satılmamasını da sağlayabilir.Bu atomik bir işlemdir. Ancak bu aynı zamanda bazı sorunlara da yol açar.Birincisi, aşırı eşzamanlılık durumunda, herhangi bir bellek işleminin ayrıntılarının performansı etkilemek için kritik öneme sahip olmasıdır, özellikle de genellikle bir disk veritabanında depolanması gereken, bu da veritabanına baskı yapar. Akla yatkın; ikincisi, eğer kullanıcı kötü niyetle bir sipariş verdiyse, sadece ödeme yapmadan sipariş verdiyse, envanter azalacak ve sunucu, kullanıcının IP'sini ve satın alma siparişlerinin sayısını sınırlayabilse de çok sayıda sipariş daha az satılacaktır. Bu da iyi bir yöntem değil.

2.2 Ödeme eksi envanter

Kullanıcının sipariş için ödeme yapmasını ve envanteri azaltmasını beklerseniz, ilk his daha az satmayacağıdır. Ancak bu eşzamanlılık mimarisinin bir tabu, çünkü aşırı eşzamanlılık altında kullanıcılar çok sayıda sipariş oluşturabilir. Envanter sıfıra düştüğünde, birçok kullanıcı aldıkları siparişler için ödeme yapamayacaklarını fark eder. Buna "aşırı satış" da denir. . Eşzamanlı işlem veritabanı disk GÇ'sinden kaçınılamaz

2.3 Stopaj envanteri

Yukarıdaki iki şema dikkate alındığında, bir sonuç çıkarabiliriz: Bir sipariş yaratıldığı sürece, veritabanı IO'su sık sık çalıştırılmalıdır. Peki, veritabanı GÇ'sinin doğrudan çalışmasını gerektirmeyen bir çözüm var mı? Envanter önce fazla satılmamasını sağlamak için çıkarılır ve ardından kullanıcı siparişleri asenkron olarak oluşturulur, böylece kullanıcılara yanıt çok daha hızlı olur; sonra çok sayıda satış nasıl garanti edilir? Kullanıcı siparişi aldıktan sonra ödeme yapmazsa ne olur? Hepimiz siparişlerin artık bir geçerlilik süresi olduğunu biliyoruz.Örneğin, kullanıcı beş dakika içinde ödeme yapmazsa, siparişin süresi dolar.Siparişin süresi dolduğunda, yeni envanter eklenecektir.Bu aynı zamanda birçok çevrimiçi perakende şirketi tarafından birçok ürünün satıldığından emin olmak için kullanılan bir çözümdür. Siparişlerin üretimi asenkrondur ve genellikle MQ ve kafka gibi anlık tüketim kuyruklarında işlenir.Sipariş hacmi nispeten küçük olduğunda siparişler çok hızlı oluşturulur ve kullanıcıların sıraya girmesi neredeyse gerekmez.

3. Envanteri düşürme sanatı

Yukarıdaki analizden, stopaj envanteri şemasının en makul olduğu açıktır. Envanteri düşürmenin ayrıntılarını daha ayrıntılı olarak analiz ediyoruz Optimizasyon için hala çok yer var Envanter nerede var? Yüksek eşzamanlılık, doğru envanter kesintisi nasıl sağlanır ve kullanıcı isteklerine hızla yanıt verilir?

Düşük eşzamanlılığa sahip tek bir makine durumunda, genellikle şu şekilde envanter kesintisi elde ederiz:

Envanterin düşülmesinin ve siparişlerin üretilmesinin atomikliğini sağlamak için, işlem işlemeyi kullanmak, ardından envanter değerlendirmesi yapmak, envanteri azaltmak ve son olarak işlemi göndermek gerekir.Tüm sürecin birçok IO'su vardır ve veri tabanının çalışması engellenir. Bu yöntem, yüksek eşzamanlılık artış sistemleri için hiç uygun değildir.

Ardından, tek makineli envanter kesintisi için planı optimize ediyoruz: Yerel kesinti . Lokal makineye belli bir miktar stok tahsis ediyor, direkt olarak hafızadaki stoğu azaltıyor ve daha sonra önceki mantığa göre asenkron olarak sipariş oluşturuyoruz. Geliştirilmiş bağımsız sistem şuna benzer:

Bu, veri tabanında sık IO işlemlerini önler ve yalnızca bellekteki işlemleri gerçekleştirerek tek bir makinenin eşzamanlılığa direnme yeteneğini büyük ölçüde geliştirir. Bununla birlikte, milyonlarca kullanıcı isteğine sahip tek bir makineye zaten direnilemez nginx, ağ isteklerini işlemek için epoll modelini kullansa da, c10k sorunu sektörde çoktan çözülmüştür. Ancak Linux sistemi altında, tüm kaynaklar dosyalardır ve ağ istekleri de öyledir.Çok sayıda dosya tanımlayıcı, işletim sisteminin anında yanıt kaybetmesine neden olur. Yukarıda nginx'in ağırlıklı denge stratejisinden bahsetmiştik. 100W kullanıcı talebinin 100 sunucuya eşit olarak dengelendiğini varsayalım, böylece tek bir makinenin dayanabileceği eşzamanlılık miktarı çok daha az olacaktır. Daha sonra, her makine için yerel olarak 100 tren bileti stoklarız ve 100 sunucuda toplam envanter hala 10.000'dir, bu da envanter siparişlerinin aşırı satılmamasını sağlar. Açıkladığımız küme mimarisi aşağıda verilmiştir:

Sorunlar birbiri ardına geldi. Yüksek eşzamanlılık durumunda, sistemin yüksek kullanılabilirliğini hala garanti edemeyiz. 100 sunucudaki iki veya üç makine, eşzamanlı trafiği kaldıramadıkları için veya başka nedenlerle çalışmıyorsa. O zaman bu sunuculardaki siparişler satılamaz, bu da siparişlerin daha az satışına yol açar. Bu sorunu çözmek için, bir sonraki hataya dayanıklı çözüm olan toplam sipariş hacminin birleşik bir yönetimini yapmamız gerekiyor. Sunucu envanteri yalnızca yerel olarak azaltmakla kalmamalı, aynı zamanda Uzaktan birleşik envanter azaltma . Uzaktan birleştirilmiş envanter azaltma işlemi ile, makinede makinenin aksama süresini önlemek için makine yüküne göre her makine için bazı ekstra "tampon envanteri" tahsis edebiliriz. Aşağıdaki mimari diyagram ile detaylı olarak inceleyelim:

Birleştirilmiş envanteri depolamak için Redis kullanıyoruz çünkü Redis çok yüksek performansa sahip ve tek bir makine QPS'nin 10W eşzamanlılığa dayanabileceği söyleniyor. Yerel envanter azaltıldıktan sonra, yerel olarak bir sipariş varsa, envanteri uzaktan düşürmek için yeniden talep ediyoruz.Hem yerel hem de uzaktan envanter azaltma başarılı olduktan sonra, kullanıcıya başarılı bir bilet kapma hatırlatıcısını geri göndereceğiz ve bu da siparişin etkili bir şekilde olmayacağından emin olabilir. Fazla satıldı. Bir makine çalışmadığında, her makinede tampon bilet ayrıldığından, aşağı makinedeki kalan biletler diğer makinelerde telafi edilebilir ve bu da çok sayıda satış sağlar. Teorik olarak, daha fazla arabellek ayarı, sistem kesinti süresini tolere edebilir, ancak çok büyük bir arabellek ayarının da yeniden işlem üzerinde belirli bir etkisi olacaktır. Redis bellek veritabanı çok yüksek bir anti-eşzamanlılığa sahip olmasına rağmen, istek yine de ağ IO üzerinden gidecektir. Aslında, bilet kapma işlemi sırasında redis isteklerinin sayısı, yerel envanter ve tampon envanterinin toplam miktarıdır, çünkü yerel envanter yetersiz olduğunda, sistem doğrudan kullanıcıya geri döner " "Tükendi" bilgi istemi, birleşik envanter kesintisi mantığı artık kullanılmayacaktır, bu da bir dereceye kadar büyük miktarda ağ talebinin yeniden sıralanmasını önler, bu nedenle arabellek değeri ayarı mimarın sistemi yüklemesini gerektirir Yetenek dikkatlice değerlendirilir.

4. Kod gösterimi

Go dili başlangıçta eşzamanlılık için tasarlanmıştır. Size tek makineli bilet kapma işleminin belirli sürecini göstermek için go dilini kullanıyorum.

4.1 Başlatma

Go paketindeki init işlevi, ana işlevden önce yürütülür ve bazı hazırlık çalışmaları esas olarak bu aşamada yapılır. Sistemimizin yapması gereken hazırlık çalışması, yerel envanteri başlatmak, uzak redis depolama birleşik envanterinin hash anahtar değerini başlatmak ve redis bağlantı havuzunu başlatmaktır; ayrıca, 1 boyutunda int tipi bir kanalın başlatılması gerekir, amaç dağıtılmış kilit işlevini gerçekleştirmektir. , Ayrıca doğrudan okuma-yazma kilitlerini kullanabilir veya kaynak rekabetinden kaçınmak için redis ve diğer yöntemleri kullanabilirsiniz, ancak kanalları kullanmak daha etkilidir. Go dilinin felsefesi budur: Paylaşılan hafıza yoluyla iletişim kurmayın, iletişim yoluyla hafızayı paylaşın . Redis kitaplığı redigo kullanır, aşağıdaki kod uygulamasıdır:

... // localSpike paket yapısı tanımlama paketi localSpiketype LocalSpike struct {LocalInStock int64 LocalSalesVolume int64} ... // remoteSpike'ın karma yapısı tanımı ve redis bağlantı havuzu paketi remoteSpike // Uzaktan sipariş depolama anahtarı değer türü RemoteSpikeKeys struct {SpikeOrderHashKey string // Seckill sipariş karma yapı anahtarı TotalInventoryKey dizesi redis'de // Karma yapısındaki toplam sipariş envanter anahtarı QuantityOfOrderKey dizesi // Karma yapı anahtarında zaten siparişlerin sayısı) // Redis bağlantı havuzu işlevini başlat NewPool () * redis.Pool {return redis .Pool {MaxIdle: 10000, MaxActive: 12000, // maks. Bağlantı sayısı Çevir: func () (redis.Conn, error) {c, err: = redis.Dial ("tcp", ": 6379") eğer err ! = nil {panic (err.Error ())} return c, err},}) ... func init () {localSpike = localSpike2.LocalSpike {LocalInStock: 150, LocalSalesVolume: 0,} remoteSpike = remoteSpike2.RemoteSpikeKeys { SpikeOrderHashKey: "ticket_hash_key", TotalInventoryKey: "ticket_total_nums", QuantityOfOrderKey: "ticket_sold_nums",} redisPool = remoteSpike2.NewPool () done = make (chan int, 1) yapıldı < -1} 4.2 Envanterin yerel kesintisi ve birleşik envanter kesintisi

Yerel envanter kesintisinin mantığı çok basittir. Kullanıcı bunu ister, satış hacmini ekler ve ardından satış hacminin yerel envanterden daha büyük olup olmadığını karşılaştırır ve bool değerini döndürür:

paket localSpike // Yerel envanter kesintisi, geri dönüş değeri func (spike * LocalSpike) LocalDeductionStock () bool {spike.LocalSalesVolume = spike.LocalSalesVolume + 1 dönüş spike.LocalSalesVolume < spike.LocalInStock}

Buradaki paylaşılan verilerin LocalSalesVolume işleminin başarmak için bir kilit kullanmak olduğuna dikkat edin, ancak yerel envanter kesintisi ve envanterin birleşik kesintisi atomik bir işlem olduğundan, kanal bunu başarmak için en üst düzeyde kullanılır, bu daha sonra tartışılacaktır. Birleştirilmiş envanter kesinti işlemi yeniden yapıldığından, redis tek iş parçacıklıdır ve ondan veri almamız, veri yazmamız ve bir dizi adımı hesaplamamız gerekir, işlemin atomikliğini sağlamak için lua betiği paketleme komutlarıyla işbirliği yapmamız gerekir:

paket remoteSpike ...... const LuaScript = `local ticket_key = KEYS local ticket_total_key = ARGV local ticket_sold_key = ARGV local ticket_total_nums = tonumber (redis.call ('HGET', ticket_key, ticket_total_key)) yerel ticket_sold_nums = tonumber (redis.call ('HGET', ticket_key, ticket_sold_key)) - Kalan bilet olup olmadığını kontrol edin, sipariş sayısını artırın ve eğer (ticket_total_nums > = ticket_sold_nums) sonra redis.call ('HINCRBY', ticket_key, ticket_sold_key, 1) end return 0` // Envanterin uzaktan birleşik kesinti işlevi (RemoteSpikeKeys * RemoteSpikeKeys) RemoteDeductionStock (conn redis.Conn) bool {lua: = redis. NewScript (1, LuaScript) sonucu, err: = redis.Int (lua.Do (conn, RemoteSpikeKeys.SpikeOrderHashKey, RemoteSpikeKeys.TotalInventoryKey, RemoteSpikeKeys.QuantityOfOrderKey)) eğer err! = Nil {return false} dönüş sonucu! = 0)

Toplam envanter ve toplam satış bilgilerini saklamak için hash yapısını kullanırız.Kullanıcı bunu talep ettiğinde, toplam satışların envanterden daha büyük olup olmadığına karar verir ve ardından ilgili bool değerini döndürürüz. Hizmete başlamadan önce, redis'in ilk envanter bilgilerini başlatmamız gerekir:

hmset ticket_hash_key "ticket_total_nums" 10000 "ticket_sold_nums" 04.3 Kullanıcı bilgilerine yanıt

Bir http hizmeti başlatıyoruz ve bir bağlantı noktasında dinliyoruz:

paket main ... func main () {http.HandleFunc ("/ buy / ticket", handleReq) http.ListenAndServe (": 3005", nil)}

Yukarıdaki tüm ilklendirme çalışmalarını yaptık ve ardından handleReq'in mantığı çok açık, bilet kapma işleminin başarılı olup olmadığına karar vermek ve bilgiyi kullanıcıya iade etmek yeterli.

package main // Yanıt sonucu bilgisini log func handleReq'e yazma isteğine göre işleme isteği fonksiyonu (w http.ResponseWriter, r * http.Request) {redisConn: = redisPool.Get () LogMsg: = "" < -done // localSpike.LocalDeductionStock () remoteSpike.RemoteDeductionStock (redisConn) {util.RespJson (w, 1, "Bilet alma başarısı", nil) LogMsg = LogMsg + "sonuç: 1, localSales:" + ise genel okuma-yazma kilidi strconv.FormatInt (localSpike.LocalSalesVolume, 10)} else {util.RespJson (w, -1, "tükendi", nil) LogMsg = LogMsg + "sonuç: 0, localSales:" + strconv.FormatInt (localSpike.LocalSalesVolume , 10)} tamamlandı < -1 // Bilet alma durumunu günlük writeLog'a yazın (LogMsg, "./stat.log")}func writeLog (msg string, logPath string) {fd, _: = os.OpenFile (logPath, os.O_RDWR | os.O_CREATE | os.O_APPEND, 0644) fd.Close () içeriğini erteleyin: = strings.Join (string {msg, "\ r \ n"}, "") buf: = bayt (içerik) fd.Write ( buf)}

Daha önce de belirtildiği gibi, envanteri çıkarırken yarış koşullarını dikkate almamız gerekiyor Burada, isteklerin verimli ve sıralı olarak yürütülmesini sağlamak için eşzamanlı okuma ve yazma işlemlerinden kaçınmak için kanalları kullanıyoruz. Basınç ölçüm istatistiklerini kolaylaştırmak için arayüzün dönüş bilgilerini ./stat.log dosyasına yazdık.

4.4 Bağımsız hizmet stres testi

Hizmeti açın, test etmek için ab stres testi aracını kullanıyoruz:

ab -n 10000 -c 100

Yerel düşük profilli mac cihazımın basınç testi bilgileri aşağıdadır

Bu ApacheBench, Sürüm 2.3'tür < $ Revizyon: 1826891 $ > Telif hakkı 1996 Adam Twiss, Zeus Technology Ltd, to The Apache Software Foundation, 127.0.0.1 (sabırlı olun) 1000 istek tamamlandı 2000 istek tamamlandı 3000 istek tamamlandı TaleplerTamamlanan 4000 istekTamamlanan 5000 istekTamamlanan 6000 istekTamamlanan 7000 istekTamamlanan 10000 istekSunucu Yazılımı: Sunucu Ana Bilgisayar Adı: 127.0.0.1Sunucu Portu: 3005Document Path: / buy / ticketDocument Length: 29 bytesConcurrency Seviyesi: 2.33 saniye 10000 Başarısız istekler: 0 Aktarılan toplam: 1370000 bayt Aktarılan HTML: 290000 bayt Saniye başına istek sayısı: 4275,96 (ortalama) İstek başına süre: 23,387 (ortalama) İstek başına süre: 0,234 (ortalama, tüm eşzamanlı istekler arasında) Aktarım hızı: 572,08 alındı Bağlantı Süreleri (ms) dakika ortalama medyan maksimum Bağlantı: 08 14,76223 İşlem: 21517,611232 Bekleme: 11113,58225 Toplam: 72322,818239P belirli bir süre içinde sunulan taleplerin yüzdesi (ms) 50% 1866% 2475% 2680% 2890% 3395% 3998% 4599% 54100% 239 (en uzun talep)

Göstergelere göre tek bir makinede saniyede 4000+ istekleri halledebiliyorum.Normal sunucuların hepsi çok çekirdekli konfigürasyonlardır ve 1W + taleplerin işlenmesinde bir problem yoktur. Günlüklere bakıldığında, tüm hizmet süreci boyunca isteklerin normal, trafiğin eşit ve redis'in de normal olduğu görüldü:

//stat.log...result:1,localSales:145result:1,localSales:146result:1,localSales:147result:1,localSales:148result:1,localSales:149result:1,localSales:150result:0,localSales: 151 sonuç: 0, yerelSatış: 152 sonuç: 0, yerelSatış: 153 sonuç: 0, yerelSatış: 154 sonuç: 0, yerelSatış: 156 ...

5. Özet ve inceleme

Genel olarak, başak sistemi çok karmaşıktır. Burada, tek bir makinenin yüksek performansa nasıl optimize edildiğini, bir kümede tek bir hata noktasından nasıl kaçınılacağını, siparişlerin aşırı satılmamasını ve bazı stratejilerin çok satıldığından emin olmak için nasıl simüle edileceğini kısaca açıklıyoruz.Tam sipariş sistemi ve sipariş ilerleme görünümü her sunucuda. Kalan biletlerin ve envanter bilgilerinin toplam envanterden kullanıcıya düzenli olarak senkronize edilmesi görevi vardır ve kullanıcı siparişin geçerlilik süresi içinde ödeme yapmaz, siparişi serbest bırakır, envanteri yeniler vb.

Yüksek eşzamanlılıklı bilet kapmanın temel mantığını uyguladık.Sistem tasarımının çok zekice olduğu, DB veritabanı IO'nun çalışmasını ve Redis ağ IO'nun yüksek eşzamanlı isteklerini önlediği söylenebilir. Hemen hemen tüm hesaplamalar bellekte. Tamamlandı ve etkin bir şekilde aşırı satış yapmayacağını, çok satmayacağını ve bazı makine arıza sürelerine tahammül edebileceğini garanti ediyor. Bence özellikle öğrenmeye ve özetlemeye değer iki nokta var:

1, Yük dengeleme, bölme ve yönetme. Yük dengeleme yoluyla, farklı trafik farklı makinelere bölünür.Her makine kendi isteklerini yerine getirir ve performansını en üst düzeye çıkarır, böylece sistem bir bütün olarak son derece yüksek eşzamanlılığa, tıpkı çalışmak gibi dayanabilir. Bir takımda herkes değerini maksimize etti ve ekibin büyümesi doğal olarak harika.

2, Eşzamanlılığı ve eşzamansızlığı uygun şekilde kullanın. Epoll ağ mimarisi modeli c10k problemini çözdüğü için zaman uyumsuzluğu sunucu tarafı geliştiriciler tarafından giderek daha fazla kabul görmüştür.Asenkron ile yapılabilecek işler asenkron ile yapılabilmektedir.Fonksiyonel demontajda beklenmedik sonuçlar elde edilebilmektedir. Nginx, node.js ve redis'e yansıtılabilir.Ağ isteklerini işlemek için kullandıkları epoll modeli, bize tek iş parçacığının hala güçlü bir güç uygulayabileceğini gösterdi. Sunucu çok çekirdekli çağına girdi. Eşzamanlı olmak için doğmuş bir dil olan Go dili, sunucunun çok çekirdekli avantajlarından mükemmel bir şekilde yararlanır. Eşzamanlı olarak işlenebilen birçok görev eşzamanlılık kullanılarak çözülebilir. Örneğin, go http isteklerini işlerken, her istek Kısacası, bir düzende yürütme: CPU'yu makul bir şekilde nasıl sıkıştırıp gereken değerini oynamasına izin vermek, her zaman keşfetmemiz ve öğrenmemiz gereken yöndür.

SpringBoot, REST arayüzünü basit ve esnek güvenlik kimlik doğrulama uygulamasını uygulamak için AOP kullanır
önceki
Salgın altında! Yerli internet şirketlerinin çalışma saatlerinin özeti
Sonraki
Spring Boot hizmeti izleme, durum denetimi, iş parçacığı bilgileri, JVM yığın bilgileri
Çin'in önde gelen İnternet şirketlerinin teknik organizasyonundaki ayarlamalar neyi gösteriyor?
Resimler ve metinler, aptalların anlayabileceği JVM bellek düzeni
ThreadLocal Röportaj Liulian sordu, tutabilir misin?
Zamanlanmış görev planı ansiklopedisi
Bilinmeyen dağıtılmış kilit uygulamalarının hepsi burada
Derinlemesine yirmi bin kelime, dağıtılmış sistemlerin ilkelerini tanıtır
JVM röportajı 4 çekim, buna dayanabilir misin?
Saniyede milyonlarca eşzamanlılık elde etmek için "IO çoğullama" kullanma prensibini biliyor musunuz?
SpringBoot + RabbitMQ, mesajın% 100'ünün başarıyla teslim edilmesini ve tüketilmesini sağlamak için
Sadece okulun iyi seçilmesi değil, aynı zamanda bu popüler ana dalların da dikkatlice referans alınması gerekir.
Tayland'da Eğitim | Tayland'da eğitim hakkında bilmediğiniz şeyler
To Top