国产一区二区91,欧美美女日韩,青草青草久热精品视频在线观看http://www.aygfsteel.com/xiaomage234/生命本就是一次凄美的漂流,記憶中放不下的,永遠(yuǎn)是孩提時(shí)代的那一份浪漫與純真!zh-cnWed, 30 Apr 2025 11:00:43 GMTWed, 30 Apr 2025 11:00:43 GMT60如何系統(tǒng)性地學(xué)習(xí)分布式系統(tǒng)?[轉(zhuǎn)]http://www.aygfsteel.com/xiaomage234/archive/2020/11/26/435735.html小馬歌小馬歌Thu, 26 Nov 2020 08:20:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2020/11/26/435735.htmlhttp://www.aygfsteel.com/xiaomage234/comments/435735.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2020/11/26/435735.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/435735.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/435735.htmlfrom:https://www.infoq.cn/article/orvjbfycnrito5qiyfhf
前言


學(xué)習(xí)一個(gè)知識(shí)之前,我覺得比較好的方式是先理解它的來龍去脈:即這個(gè)知識(shí)產(chǎn)生的過程,它解決了什么問題,它是怎么樣解決的,還有它引入了哪些新的問題(沒有銀彈),這樣我們才能比較好的抓到它的脈絡(luò)和關(guān)鍵點(diǎn),不會(huì)一開始就迷失在細(xì)節(jié)中。


所以,在學(xué)習(xí)分布式系統(tǒng)之前,我們需要解決的第一個(gè)問題是:分布式系統(tǒng)解決了什么問題?


分布式系統(tǒng)解決了什么問題?


第一個(gè)是單機(jī)性能瓶頸導(dǎo)致的成本問題,由于摩爾定律失效,廉價(jià) PC 機(jī)性能的瓶頸無法繼續(xù)突破,小型機(jī)和大型機(jī)能提高更高的單機(jī)性能,但是成本太大高,一般的公司很難承受;


第二個(gè)是用戶量和數(shù)據(jù)量爆炸性的增大導(dǎo)致的成本問題,進(jìn)入互聯(lián)網(wǎng)時(shí)代,用戶量爆炸性的增大,用戶產(chǎn)生的數(shù)據(jù)量也在爆炸性的增大,但是單個(gè)用戶或者單條數(shù)據(jù)的價(jià)值其實(shí)比軟件時(shí)代(比如銀行用戶)的價(jià)值是只低不高,所以必須尋找更經(jīng)濟(jì)的方案;


第三個(gè)是業(yè)務(wù)高可用的要求,對(duì)于互聯(lián)網(wǎng)的產(chǎn)品來說,都要求 7 * 24 小時(shí)提供服務(wù),無法容忍停止服務(wù)等故障,而要提供高可用的服務(wù),唯一的方式就是增加冗余來完成,這樣就算單機(jī)系統(tǒng)可以支撐的服務(wù),因?yàn)楦呖捎玫囊螅矔?huì)變成一個(gè)分布式系統(tǒng)。


基于上面的三個(gè)原因可以看出,在互聯(lián)網(wǎng)時(shí)代,單機(jī)系統(tǒng)是無法解決成本和高可用問題的,但是這兩個(gè)問題對(duì)幾乎對(duì)所有的公司來說都是非常關(guān)鍵的問題,所以,從單機(jī)系統(tǒng)到分布式系統(tǒng)是無法避免的技術(shù)大潮流。


分布式系統(tǒng)是怎么來解決問題的?


那么,分布式系統(tǒng)是怎么來解決單機(jī)系統(tǒng)面臨的成本和高可用問題呢?


其實(shí)思路很簡(jiǎn)單,就是將一些廉價(jià)的 PC 機(jī)通過網(wǎng)絡(luò)連接起來,共同完成工作,并且在系統(tǒng)中提供冗余來解決高可用的問題。


分布式系統(tǒng)引入了哪些新的問題?


我們來看分布式系統(tǒng)的定義:分布式系統(tǒng)是由一組通過網(wǎng)絡(luò)進(jìn)行通信、為了完成共同的任務(wù)而協(xié)調(diào)工作的計(jì)算機(jī)節(jié)點(diǎn)組成的系統(tǒng)。在定義中,我們可用看出,分布式系統(tǒng)它通過多工作節(jié)點(diǎn)來解決單機(jī)系統(tǒng)面臨的成本和可用性問題,但是它引入了對(duì)分布式系統(tǒng)內(nèi)部工作節(jié)點(diǎn)的協(xié)調(diào)問題。


我們經(jīng)常說掌握一個(gè)知識(shí)需要理解它的前因后果,對(duì)于分布式系統(tǒng)來說,前因是「分布式系統(tǒng)解決了什么問題」,后果是「它是怎么做內(nèi)部工作節(jié)點(diǎn)的協(xié)調(diào)」,所以我們要解決的第二個(gè)問題是:分布式系統(tǒng)是怎么做內(nèi)部工作節(jié)點(diǎn)協(xié)調(diào)的?


分布式計(jì)算引入了哪些新的問題?


先從簡(jiǎn)單的情況入手,對(duì)于分布式計(jì)算(無狀態(tài))的情況,系統(tǒng)內(nèi)部的協(xié)調(diào)需要做哪些工作:


1.怎么樣找到服務(wù)?


在分布式系統(tǒng)內(nèi)部,會(huì)有不同的服務(wù)(角色),服務(wù) A 怎么找到服務(wù) B 是需要解決的問題,一般來說服務(wù)注冊(cè)與發(fā)現(xiàn)機(jī)制是常用的思路,所以可以了解一下服務(wù)注冊(cè)發(fā)現(xiàn)機(jī)制實(shí)現(xiàn)原理,并且可以思考服務(wù)注冊(cè)發(fā)現(xiàn)是選擇做成 AP 還是 CP 系統(tǒng)更合理(嚴(yán)格按 CAP 理論說,我們目前使用的大部分系統(tǒng)很難滿足 C 或者 A 的,所以這里只是通常意義上的 AP 或者 CP);


2.怎么樣找到實(shí)例?


找到服務(wù)后,當(dāng)前的請(qǐng)求應(yīng)該選擇發(fā)往服務(wù)的哪一個(gè)實(shí)例呢?一般來說,如果同一個(gè)服務(wù)的實(shí)例都是完全對(duì)等的(無狀態(tài)),那么按負(fù)載均衡策略來處理就足夠(輪詢、權(quán)重、hash、一致性 hash,fair 等各種策略的適用場(chǎng)景);如果同一個(gè)服務(wù)的實(shí)例不是對(duì)等的(有狀態(tài)),那么需要通過路由服務(wù)(元數(shù)據(jù)服務(wù)等)先確定當(dāng)前要訪問的請(qǐng)求數(shù)據(jù)做哪一個(gè)實(shí)例上,然后再進(jìn)行訪問。


3.怎么樣避免雪崩?


系統(tǒng)雪崩是指故障的由于正反饋循序?qū)е虏粩鄶U(kuò)大規(guī)則的故障。一次雪崩通常是由于整個(gè)系統(tǒng)中一個(gè)很小的部分出現(xiàn)故障于引發(fā),進(jìn)而導(dǎo)致系統(tǒng)其它部分也出現(xiàn)故障。比如系統(tǒng)中某一個(gè)服務(wù)的一個(gè)實(shí)例出現(xiàn)故障,導(dǎo)致負(fù)載均衡將該實(shí)例摘除而引起其它實(shí)例負(fù)載升高,最終導(dǎo)致該服務(wù)的所有實(shí)例像多米諾骨牌一樣一個(gè)一個(gè)全部出現(xiàn)故障。


避免雪崩總體的策略比較簡(jiǎn)單,只要是兩個(gè)思路,一個(gè)是快速失敗和降級(jí)機(jī)制(熔斷、降級(jí)、限流等),通過快速減少系統(tǒng)負(fù)載來避免雪崩的發(fā)生;另一個(gè)為彈性擴(kuò)容機(jī)制,通過快速增加系統(tǒng)的服務(wù)能力來避免雪崩的發(fā)生。這個(gè)根據(jù)不同的場(chǎng)景可以做不同的選擇,或者兩個(gè)策略都使用。


一般來說,快速失敗會(huì)導(dǎo)致部分的請(qǐng)求失敗,如果分布式系統(tǒng)內(nèi)部對(duì)一致性要求很高的話,快速失敗會(huì)帶來系統(tǒng)數(shù)據(jù)不一致的問題,彈性擴(kuò)容會(huì)是一個(gè)比較好的選擇,但是彈性擴(kuò)容的實(shí)現(xiàn)成本和響應(yīng)時(shí)間比快速失敗要大得多。


4.怎么樣監(jiān)控告警?


對(duì)于一個(gè)分布式系統(tǒng),如果我們不能很清楚地了解內(nèi)部的狀態(tài),那么高可用是沒有辦法完全保障的,所以對(duì)分布式系統(tǒng)的監(jiān)控(比如接口的時(shí)延和可用性等信息),分布式追蹤 Trace,模擬故障的混沌工程,以及相關(guān)的告警等機(jī)制是一定要完善的;


分布式存儲(chǔ)引入了哪些新的問題?


接下來我們?cè)賮砜捶植际酱鎯?chǔ)(有狀態(tài))的內(nèi)部的協(xié)調(diào)是怎么做的,同時(shí),前面介紹的分布式計(jì)算的協(xié)調(diào)方式在分布式存儲(chǔ)中同樣適用,就不再重復(fù)了:


1.分布式系統(tǒng)的理論與衡權(quán)


ACID、BASE 和 CAP 理論,了解這三個(gè)主題,推薦這一篇文章以及文章后面相關(guān)的參考文獻(xiàn):


英文版本:https://www.infoq.com/articles/cap-twelve-years-later-how-the-rules-have-changed/


中文版本:https://www.infoq.cn/article/cap-twelve-years-later-how-the-rules-have-changed/


2.怎么樣做數(shù)據(jù)分片?


單機(jī)的存儲(chǔ)能力是不可能存儲(chǔ)所有的數(shù)據(jù)的,所以需要解決怎么將數(shù)據(jù)按一定的規(guī)則分別存儲(chǔ)到不同的機(jī)器上,目前使用比較多的方案為:Hash、Consistent Hash 和 Range Based 分片策略,可以了解一下它們的優(yōu)缺點(diǎn)和各自的應(yīng)用場(chǎng)景;


3.怎么樣做數(shù)據(jù)復(fù)制?


為什么滿足系統(tǒng)的高可用要求,需要對(duì)數(shù)據(jù)做冗余處理,目前的方案主要為:中心化方案(主從復(fù)制、一致性協(xié)議比如 Raft 和 Paxos 等)和 去中心化的方案(Quorum 和 Vector Clock)了解一下它們的優(yōu)缺點(diǎn)和各自的應(yīng)用場(chǎng)景,以及對(duì)系統(tǒng)外部表現(xiàn)出來的數(shù)據(jù)一致性級(jí)別(線性一致性、順序一致性、最終一致性等);


4.怎么樣做分布式事務(wù)?


對(duì)于分布式系統(tǒng)來說,要實(shí)現(xiàn)事務(wù),首先需要有對(duì)并發(fā)事務(wù)進(jìn)行排序的能力,這樣在事務(wù)沖突的時(shí)候,確認(rèn)哪個(gè)事務(wù)提供成功,哪個(gè)事務(wù)提交失敗。對(duì)于單機(jī)系統(tǒng)來說這個(gè)完全不是問題,簡(jiǎn)單通過時(shí)間戳加序號(hào)的方式就可以實(shí)現(xiàn),但是對(duì)于分布式系統(tǒng)來說,系統(tǒng)中機(jī)器的時(shí)間不能完全同步,并且單臺(tái)機(jī)器序號(hào)也沒用全局意義,按上面的方式說行不通的。不過整個(gè)系統(tǒng)選一臺(tái)機(jī)器按單機(jī)的模式生產(chǎn)事務(wù) ID 是可以的,同城多中心和短距離的異地多中心都沒有問題,不過想做成全球分布式系統(tǒng)的話,那么每一次事務(wù)都要去一個(gè)節(jié)點(diǎn)去獲取事務(wù) ID 的成本太高(比如中國(guó)杭州到美國(guó)東部的 RTT 為 200 + ms ),Google 的 Spanner 是通過 GPS 和原子鐘實(shí)現(xiàn) TrueTime API 來解決這個(gè)問題從而實(shí)現(xiàn)全球分布式數(shù)據(jù)庫的。


有了事務(wù) ID 后,通過 2PC 或者 3PC 協(xié)議來實(shí)現(xiàn)分布式事務(wù)的原子性,其他部分和單機(jī)事務(wù)差別不大,就不再細(xì)說來。


進(jìn)階學(xué)習(xí)階段


到這里,對(duì)分布式系統(tǒng)脈絡(luò)上有了基本的概念,接下來開始進(jìn)入細(xì)節(jié)學(xué)習(xí)階段,這也是非常幸苦的階段,對(duì)于分布式系統(tǒng)的理解深入與否,對(duì)細(xì)節(jié)的深入度是很重要的評(píng)價(jià)指標(biāo),畢竟魔鬼在細(xì)節(jié)。這里可以往兩個(gè)方面進(jìn)行系統(tǒng)的學(xué)習(xí):


1.從實(shí)踐出發(fā)


研究目前比較常用的分布式系統(tǒng)的設(shè)計(jì),HDFS 或者 GFS(分布式文件系統(tǒng))、Kafka 和 Pulsar(分布式消息隊(duì)列),Redis Cluster 和 Codis(分布式緩存),MySQL 的分庫分表(傳統(tǒng)關(guān)系型數(shù)據(jù)庫的分布式方案),MongoDB 的 Replica Set 和 Sharing 機(jī)制集以及去中心化的 Cassandra(NoSQL 數(shù)據(jù)庫),中心化的 TiDB 和去中心化的 CockroachDB(NewSQL),以及一些微服務(wù)框架等;


2.從理論出發(fā)


從理論出發(fā),研究分布式相關(guān)的論文,這里推薦一本書「Designing Data-Intensive Applications」(中文版本:數(shù)據(jù)密集型應(yīng)用系統(tǒng)設(shè)計(jì)),先整體看書,對(duì)比較感興趣的章節(jié),再讀一讀該章節(jié)中涉及到的相關(guān)參考文獻(xiàn)。


總結(jié)


本文從分布式系統(tǒng)解決的問題開始,再討論它是怎么樣來解決問題的,最后討論了它引入了哪些新的問題,并且討論這些新問題的解決辦法,這個(gè)就是分布式系統(tǒng)大概的知識(shí)脈絡(luò)。掌握這個(gè)知識(shí)脈絡(luò)后,那么就可以從實(shí)踐和理論兩個(gè)角度結(jié)合起來深入細(xì)節(jié)研究分布式系統(tǒng)了。


參考


知乎 | 如何系統(tǒng)性的學(xué)習(xí)分布式系統(tǒng)


Martin Kleppmann.Designing Data-Intensive Applications


CAP Twelve Years Later: How the “Rules” Have Changed



小馬歌 2020-11-26 16:20 發(fā)表評(píng)論
]]>
基帶、射頻,到底是干什么用的?http://www.aygfsteel.com/xiaomage234/archive/2020/11/24/435733.html小馬歌小馬歌Tue, 24 Nov 2020 02:41:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2020/11/24/435733.htmlhttp://www.aygfsteel.com/xiaomage234/comments/435733.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2020/11/24/435733.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/435733.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/435733.html閱讀全文

小馬歌 2020-11-24 10:41 發(fā)表評(píng)論
]]>
Cat.1 現(xiàn)狀[轉(zhuǎn)]http://www.aygfsteel.com/xiaomage234/archive/2020/11/06/435716.html小馬歌小馬歌Fri, 06 Nov 2020 06:36:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2020/11/06/435716.htmlhttp://www.aygfsteel.com/xiaomage234/comments/435716.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2020/11/06/435716.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/435716.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/435716.html

隨著紫光展銳、ASR 等芯片廠商發(fā)布性價(jià)比更高的 Cat.1 芯片之后,Cat.1 模組廠商扎堆發(fā)布了自家的模組,
使得市場(chǎng)上的 Cat.1 模組價(jià)格已經(jīng)迅速降至 45-60 元,玩家眾多,競(jìng)爭(zhēng)慘烈,基本重走 NB-IOT 的老路 —— 量未起,價(jià)已跌。

Cat.1 芯片原廠:

  • 高通 MDM9207-1(2016 年發(fā)布)

  • 紫光展銳春藤 8910DM(28nm工藝,集成藍(lán)牙和WiFi 室內(nèi)定位)

  • 翱捷 ASR3601

Cat.1 模組廠商(不完全統(tǒng)計(jì)):

  • 中移物聯(lián)網(wǎng)

  • 移遠(yuǎn)通信

  • 合宙電子

  • 移柯通信

  • 域格信息

  • 廣和通

  • 芯訊通

  • 高新興物聯(lián)

  • 美格智能

  • 有方科技

  • 有人信息

  • 信位通訊

  • 銳騏(廈門)電子

  • 深圳信可通訊

Cat.1 優(yōu)勢(shì)

  • 相對(duì) NB-IOT,其通信速率優(yōu)勢(shì)明顯

  • 相對(duì) eMTC,其網(wǎng)絡(luò)成本低

  • 相對(duì) Cat.4,其具有一定的成本優(yōu)勢(shì)

Cat.1 劣勢(shì):

  • 現(xiàn)階段芯片廠家少

    國(guó)外以高通為主,輔以 Sequans、Altair。

    國(guó)內(nèi)主要是展銳和翱捷。

  • 現(xiàn)階段價(jià)格偏高

    NB-IoT、Cat.1、Cat.4 模組價(jià)格:


cat1 的主要市場(chǎng)和應(yīng)用場(chǎng)景:

Cat.1 仍處于商用初期,落地的應(yīng)用場(chǎng)景和案例還較少,一些明確的場(chǎng)景包括了共享、金融支付、工業(yè)控制、車載支付、公網(wǎng)對(duì)講、POS 等等。

總結(jié)

工信部辦公廳發(fā)布了《關(guān)于深入推進(jìn)移動(dòng)物聯(lián)網(wǎng)全面發(fā)展的通知》(以下簡(jiǎn)稱《通知》)同時(shí)為 NB-IOT 和 Cat.1 站臺(tái),未來 NB-IOT 依舊很香,Cat.1 則前途大好。

隨著新基建的啟動(dòng),5G 打頭,未來將是 NB-IOT、4G(包括 Cat.1)、5G 共同承載蜂窩物聯(lián)網(wǎng)的連接,以應(yīng)對(duì)不同層次的物聯(lián)網(wǎng)業(yè)務(wù)需求。



小馬歌 2020-11-06 14:36 發(fā)表評(píng)論
]]>
QoS等級(jí) 與 會(huì)話[轉(zhuǎn)]http://www.aygfsteel.com/xiaomage234/archive/2020/10/12/435690.html小馬歌小馬歌Mon, 12 Oct 2020 06:19:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2020/10/12/435690.htmlhttp://www.aygfsteel.com/xiaomage234/comments/435690.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2020/10/12/435690.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/435690.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/435690.html

背景

QoS 等級(jí) 與 通信的流程有關(guān),直接影響了整個(gè)通信。而且篇幅比較長(zhǎng),所以我覺得應(yīng)該單獨(dú)拎出來講一下。

概念

QoS 代表了 服務(wù)質(zhì)量等級(jí)。 設(shè)置上,由2 位 的二進(jìn)制控制,且值不允許為 3(0x11)。

QoS值Bit 2Bit 1描述
000最多分發(fā)一次
101至少分發(fā)一次
210只分發(fā)一次
-11保留位

要注意的是,QoS 是 Sender 和 Receiver 之間達(dá)成的協(xié)議,不是 Publisher 和 Subscriber 之間達(dá)成的協(xié)議。

也就是說 Publisher 發(fā)布一條 QoS1 的消息,只能保證 Broker 能至少收到一次這個(gè)消息;至于對(duì)應(yīng)的 Subscriber 能否至少收到一次這個(gè)消息,還要取決于 Subscriber 在 Subscribe 的時(shí)候和 Broker 協(xié)商的 QoS 等級(jí)。

這里又牽扯出一個(gè)概念:"QoS 降級(jí)":在 MQTT 協(xié)議中,從 Broker 到 Subscriber 這段消息傳遞的實(shí)際 QoS 等于 "Publisher 發(fā)布消息時(shí)指定的 QoS 等級(jí)和 Subscriber 在訂閱時(shí)與 Broker 協(xié)商的 QoS 等級(jí),這兩個(gè) QoS 等級(jí)中的最小那一個(gè)。"

QoS 0 的通信時(shí)序圖

此時(shí),整個(gè)過程中的 Sender 不關(guān)心 Receiver 是否收到消息,它"盡力"發(fā)完消息,至于是否有人收到,它不在乎。

發(fā)布者服務(wù)器訂閱者PUBLISH (QoS0,Msg-A)PUBLISH(QoS0,Msg-A)Delete Msg-A發(fā)布者服務(wù)器訂閱者QoS 0:At most one(Fire and forget)

QoS1 的通信時(shí)序圖

此時(shí),Sender 發(fā)送的一條消息,Receiver 至少能收到一次,也就是說 Sender 向 Receiver 發(fā)送消息,如果發(fā)送失敗,會(huì)繼續(xù)重試,直到 Receiver 收到消息為止,但是因?yàn)橹貍鞯脑颍?code style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !important; font-size: 12px !important; line-height: 1.8; margin: 0px 4px !important; vertical-align: middle; display: inline; overflow-x: auto; background-color: rgba(27, 31, 35, 0.05) !important; border: none !important; padding: 0.2em 0.4em !important; border-radius: 3px !important;">Receiver 有可能會(huì)收到重復(fù)的消息;

發(fā)布者服務(wù)器訂閱者Store (Msg-A)PUBLISH (QoS1,Msg-A)Store (Msg-A)PUBLISH (QoS1,Msg-A)PUBACK (QoS1)Delete (Msg-A)PUBACK (QoS1,Msg-A)Delete (Msg-A)發(fā)布者服務(wù)器訂閱者QoS 1:At least one

1)Sender 向 Receiver 發(fā)送一個(gè)帶有消息數(shù)據(jù)的 PUBLISH 包, 并在本地保存這個(gè) PUBLISH 包。

2)Receiver 收到 PUBLISH 包以后,向 Sender 發(fā)送一個(gè) PUBACK 數(shù)據(jù)包,PUBACK 數(shù)據(jù)包沒有消息體(Payload),在可變頭中(Variable header)中有一個(gè)包標(biāo)識(shí)(Packet Identifier),和它收到的 PUBLISH 包中的 Packet Identifier 一致。

3)Sender 收到 PUBACK 之后,根據(jù) PUBACK 包中的 Packet Identifier 找到本地保存的 PUBLISH 包,然后丟棄掉,一次消息的發(fā)送完成。

4)如果 Sender 在一段時(shí)間內(nèi)沒有收到 PUBLISH 包對(duì)應(yīng)的 PUBACK,它將該 PUBLISH 包的 DUP 標(biāo)識(shí)設(shè)為 1(代表是重新發(fā)送的 PUBLISH 包),然后重新發(fā)送該 PUBLISH 包。重復(fù)這個(gè)流程,直到收到 PUBACK,然后執(zhí)行第 3 步。

QoS 2 的通信時(shí)序圖

QoS2 不僅要確保 Receiver 能收到 Sender 發(fā)送的消息,還要保證消息不重復(fù)。它的重傳和應(yīng)答機(jī)制就要復(fù)雜一些,同時(shí)開銷也是最大的。

Sender 發(fā)送的一條消息,Receiver 確保能收到而且只收到一次,也就是說 Sender 盡力向 Receiver 發(fā)送消息,如果發(fā)送失敗,會(huì)繼續(xù)重試,直到 Receiver 收到消息為止,同時(shí)保證 Receiver 不會(huì)因?yàn)橄⒅貍鞫盏街貜?fù)的消息。

發(fā)布者服務(wù)器訂閱者Store (Msg-A)PUBLISH (QoS2,Msg-A,DUP=0)Store (Msg-A)PUBREC (QoS2,Msg-A)PUBREL (QoS2,Msg-A)PUBLISH (QoS2,Msg-A,DUP=0)PUBCOMP (QoS2,Msg-A)Delete (Msg-A)Store (Msg-A)PUBREC (QoS2,Msg-A)PUBREL (QoS2,Msg-A)Notify (Msg-A)PUBCOMP (QoS2,Msg-A)Delete (Msg-A)Delete (Msg-A)發(fā)布者服務(wù)器訂閱者QoS 2:Exactly one

QoS 使用 2 套請(qǐng)求/應(yīng)答流程(一個(gè) 4 段的握手)來確保 Receiver 收到來自 Sender 的消息,且不重復(fù):

1)Sender 發(fā)送 QoS 為 2 的 PUBLISH 數(shù)據(jù)包,數(shù)據(jù)包 Packet Identifier 為 P,并在本地保存該 PUBLISH 包;

2)Receiver 收到 PUBLISH 數(shù)據(jù)包以后,在本地保存 PUBLISH 包的 Packet Identifier P,并回復(fù) Sender 一個(gè) PUBREC 數(shù)據(jù)包,PUBREC 數(shù)據(jù)包可變頭中的 Packet Identifier 為 P,沒有消息體(Payload);

3)當(dāng) Sender 收到 PUBREC,它就可以安全地丟棄掉初始的 Packet Identifier 為 P 的 PUBLISH 數(shù)據(jù)包,同時(shí)保存該 PUBREC 數(shù)據(jù)包,同時(shí)回復(fù) Receiver 一個(gè) PUBREL 數(shù)據(jù)包,PUBREL 數(shù)據(jù)包可變頭中的 Packet Identifier 為 P,沒有消息體;如果 Sender 在一定時(shí)間內(nèi)沒有收到 PUBREC,它會(huì)把 PUBLISH 包的 DUP 標(biāo)識(shí)設(shè)為 1,重新發(fā)送該 PUBLISH 數(shù)據(jù)包(Payload);

4)當(dāng) Receiver 收到 PUBREL 數(shù)據(jù)包,它可以丟棄掉保存的 PUBLISH 包的 Packet Identifier P,并回復(fù) Sender 一個(gè) PUBCOMP 數(shù)據(jù)包,PUBCOMP 數(shù)據(jù)包可變頭中的 Packet Identifier 為 P,沒有消息體(Payload);

5)當(dāng) Sender 收到 PUBCOMP 包,那么它認(rèn)為數(shù)據(jù)包傳輸已完成,它會(huì)丟棄掉對(duì)應(yīng)的 PUBREC 包。如果 Sender 在一定時(shí)間內(nèi)沒有收到 PUBCOMP 包,它會(huì)重新發(fā)送 PUBREL 數(shù)據(jù)包。

我們可以看到在 QoS2 中,完成一次消息的傳遞,Sender 和 Reciever 之間至少要發(fā)送四個(gè)數(shù)據(jù)包,QoS2 是最安全也是最慢的一種 QoS 等級(jí)了。

QoS 和會(huì)話(Session)

客戶端的會(huì)話狀態(tài)包括:

  • 已經(jīng)發(fā)送給服務(wù)端,但是還沒有完成確認(rèn)的QoS 1和QoS 2級(jí)別的消息
  • 已從服務(wù)端接收,但是還沒有完成確認(rèn)的QoS 2級(jí)別的消息。

服務(wù)端的會(huì)話狀態(tài)包括:

  • 會(huì)話是否存在,即使會(huì)話狀態(tài)的其它部分都是空。
  • 客戶端的訂閱信息。
  • 已經(jīng)發(fā)送給客戶端,但是還沒有完成確認(rèn)的QoS 1和QoS 2級(jí)別的消息。
  • 即將傳輸給客戶端的QoS 1和QoS 2級(jí)別的消息。
  • 已從客戶端接收,但是還沒有完成確認(rèn)的QoS 2級(jí)別的消息。
  • 可選,準(zhǔn)備發(fā)送給客戶端的QoS 0級(jí)別的消息。

保留消息不是服務(wù)端會(huì)話狀態(tài)的一部分,會(huì)話終止時(shí)不能刪除保留消息。

如果 Client 想接收離線消息,必須使用持久化的會(huì)話(CONNECT報(bào)文中可變頭(byte8[1])Clean Session = 0)連接到 Broker,這樣 Broker 才會(huì)存儲(chǔ) Client 在離線期間沒有確認(rèn)接收的 QoS 大于 1 的消息。

QoS 等級(jí)的選擇

在以下情況下你可以選擇 QoS0

  • Client 和 Broker 之間的網(wǎng)絡(luò)連接非常穩(wěn)定,例如一個(gè)通過有線網(wǎng)絡(luò)連接到 Broker 的測(cè)試用 Client;
  • 可以接受丟失部分消息,比如你有一個(gè)傳感器以非常短的間隔發(fā)布狀態(tài)數(shù)據(jù),所以丟一些也可以接受;
  • 你不需要離線消息。

在以下情況下你應(yīng)該選擇 QoS1:

  • 你需要接收所有的消息,而且你的應(yīng)用可以接受并處理重復(fù)的消息;
  • 你無法接受 QoS2 帶來的額外開銷,QoS1 發(fā)送消息的速度比 QoS2 快很多。

在以下情況下你應(yīng)該選擇 QoS2:

  • 你的應(yīng)用必須接收到所有的消息,而且你的應(yīng)用在重復(fù)的消息下無法正常工作,同時(shí)你也能接受 QoS2 帶來的額外開銷。

實(shí)際上,QoS1 是應(yīng)用最廣泛的 QoS 等級(jí),QoS1 發(fā)送消息的速度很快,而且能夠保證消息的可靠性。雖然使用 QoS1 可能會(huì)收到重復(fù)的消息,但是在應(yīng)用程序里面處理重復(fù)消息,通常并不是件難事。



小馬歌 2020-10-12 14:19 發(fā)表評(píng)論
]]>
性能問題定位:工具使用【轉(zhuǎn)】http://www.aygfsteel.com/xiaomage234/archive/2019/04/19/433725.html小馬歌小馬歌Fri, 19 Apr 2019 03:04:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2019/04/19/433725.htmlhttp://www.aygfsteel.com/xiaomage234/comments/433725.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2019/04/19/433725.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/433725.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/433725.htmlhttp://zhulongchao.com/blog/performance-trace.html

1.網(wǎng)速測(cè)試

安裝iperf

yum install epel-release 從epel源中安裝 yum install -y  iperf 

帶寬檢測(cè)

iperf -s 開啟服務(wù)端  iperf -c ip 

丟包問題

tcpdump進(jìn)行抓包  tcpdump -i eth0 -s 3000 port 8080 -w /home/tomcat.pcap  對(duì)于抓包文件采用wireshark進(jìn)行分析  丟包(TCP DUP ACK) 重傳(retransmission),超時(shí)重傳, 

2.cdn性能測(cè)試

cdn 緩存,回源問題    304請(qǐng)求,瀏覽器是否使用本地緩存。比較last_modified 和if_modified_since  通過實(shí)踐戳來判斷,瀏覽器緩存和cdn緩存 

3.DNS基礎(chǔ)

路由解析

泛域名解析

4.分布式服務(wù)鏈路追蹤

http入口產(chǎn)生一個(gè)traceId  分發(fā)到rpc調(diào)用,cache,db,jms調(diào)用鏈路中  google的著名論文dapper和zipkin  日志聚合,綁定鏈路日志和業(yè)務(wù)日志  采樣采集,慢請(qǐng)求,異常服務(wù)。  日志量大。日志異步寫入,環(huán)狀數(shù)組,日志組件自研  共享信息放在ThreadLocal中。比如traceId 

5.網(wǎng)卡性能問題定位

tsar -l  -i 1 --traffic 查看網(wǎng)卡的進(jìn)出流量 

6.CPU性能問題定位

tsar -l  -i 1 --cpu  軟件問題定位,perf 采樣所有進(jìn)程數(shù)據(jù)  perf record -F 99 -a -g -- sleep 30  java進(jìn)程的函數(shù)map:java -cp attach-main.jar:$JAVA_HOME/lib/tools.jar net.virtualvoid.perf.AttachOnce PID  輸出函數(shù)和地址的map  輸出火焰圖 perf script | stackcollapse-perf.pl | flamegraph.pl --color=java --hash > flamegraph.svg 

7.內(nèi)存性能問題定位

-堆內(nèi)內(nèi)存問題,

采用jmap dump內(nèi)存,采用離線工具分析  jprofile、mat 

-堆外內(nèi)存問題

a.google-perftools

yum install -y google-perftools graphviz  export LD_PRELOAD=/usr/lib64/libtcmalloc.so.4  export HEAPPROFILE=/home/testGperf.prof  執(zhí)行程序,結(jié)束程序,生成prof  分析prof  生成svg, pdf,text pprof --svg $JAVA_HOME/bin/java testGperf.prof.0001.heap > test.svg  pprof --pdf $JAVA_HOME/bin/java testGperf.prof.0001.heap > test.pdf  pprof --text $JAVA_HOME/bin/java testGperf.prof.0001.heap > test.txt 

b.jemalloc定位(優(yōu)勢(shì),適合長(zhǎng)時(shí)間trace)

sudo apt-get install graphviz 編譯安裝 ./configure –enable-prof –enable-stats –enable-debug –enable-fill make make install

運(yùn)行配置 export MALLOC_CONF=”prof:true,prof_gdump:true,prof_prefix:/home/jedump/jez,lg_prof_interval:30,lg_prof_sample:17”

export LD_PRELOAD=/usr/local/lib/libjemalloc.so.2 運(yùn)行 java -jar target/spring-boot-jemalloc-example-0.0.1-SNAPSHOT.jar

jeprof –show_bytes –svg jez.*.heap > app-profiling.svg

注明:如果在docker容器中,推薦用pprof,jemalloc只顯示函數(shù)地址,不顯示函數(shù)名

8.機(jī)器資源配額問題

/etc/security/limits.conf

  • soft nofile 65536
  • hard nofile 65536

控制該用戶文件句柄數(shù)

9.磁盤性能問題定位

tsar -l -i 1 –io



小馬歌 2019-04-19 11:04 發(fā)表評(píng)論
]]>
Java堆外內(nèi)存排查小結(jié)【轉(zhuǎn)】http://www.aygfsteel.com/xiaomage234/archive/2019/03/30/433695.html小馬歌小馬歌Sat, 30 Mar 2019 03:44:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2019/03/30/433695.htmlhttp://www.aygfsteel.com/xiaomage234/comments/433695.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2019/03/30/433695.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/433695.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/433695.htmlhttps://blog.csdn.net/lycyingO/article/details/80854669


 版權(quán)聲明:微信公眾號(hào)《小姐姐味道》,轉(zhuǎn)載注明出處 https://blog.csdn.net/lycyingO/article/details/80854669
簡(jiǎn)介
JVM堆外內(nèi)存難排查但經(jīng)常會(huì)出現(xiàn)問題,這可能是目前最全的JVM堆外內(nèi)存排查思路。
通過本文,你應(yīng)該了解:
pmap 命令
gdb 命令
perf 命令
內(nèi)存 RSS、VSZ的區(qū)別
java NMT
起因
這幾天遇到一個(gè)比較奇怪的問題,覺得有必要和大家分享一下。我們的一個(gè)服務(wù),運(yùn)行在docker上,在某個(gè)版本之后,占用的內(nèi)存開始增長(zhǎng),直到docker分配的內(nèi)存上限,但是并不會(huì)OOM。版本的更改如下:
升級(jí)了基礎(chǔ)軟件的版本
將docker的內(nèi)存上限由4GB擴(kuò)展到8GB
上上個(gè)版本的一項(xiàng)變動(dòng)是使用了EhCache的Heap緩存
沒有讀文件,也沒有mmap操作
使用jps 查看啟動(dòng)參數(shù),發(fā)現(xiàn)分配了大約3GB的堆內(nèi)存
[root]$ jps -v
75 Bootstrap -Xmx3000m -Xms3000m  -verbose:gc -Xloggc:/home/logs/gc.log -XX:CMSInitiatingOccupancyFraction=80 -XX:+UseCMSCompactAtFullCollection -XX:MaxTenuringThreshold=10 -XX:MaxPermSize=128M -XX:SurvivorRatio=3 -XX:NewRatio=2 -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
使用ps查看進(jìn)程使用的內(nèi)存和虛擬內(nèi)存 ( Linux內(nèi)存管理 )。除了虛擬內(nèi)存比較高達(dá)到17GB以外,實(shí)際使用的內(nèi)存RSS也夸張的達(dá)到了7GB,遠(yuǎn)遠(yuǎn)超過了-Xmx的設(shè)定。
[root]$ ps -p 75 -o rss,vsz  
 
RSS    VSZ 7152568 17485844
原創(chuàng)文章,轉(zhuǎn)載注明出處 (http://sayhiai.com)
排查過程
明顯的,是有堆外內(nèi)存的使用,不太可能是由于EhCache引起的(因?yàn)槲覀兪褂昧薶eap方式)。了解到基礎(chǔ)軟件的升級(jí)涉及到netty版本升級(jí),netty會(huì)用到一些DirectByteBuffer,第一輪排查我們采用如下方式:
jmap -dump:format=b,file=75.dump 75 通過分析堆內(nèi)存找到DirectByteBuffer的引用和大小
部署一個(gè)升級(jí)基礎(chǔ)軟件之前的版本,持續(xù)觀察
部署另一個(gè)版本,更改EhCache限制其大小到1024M
考慮到可能由Docker的內(nèi)存分配機(jī)制引起,部署一實(shí)例到實(shí)體機(jī)
結(jié)果4個(gè)環(huán)境中的服務(wù),無一例外的都出現(xiàn)了內(nèi)存超用的問題。問題很奇怪,寶寶睡不著覺。
pmap
為了進(jìn)一步分析問題,我們使用pmap查看進(jìn)程的內(nèi)存分配,通過RSS升序序排列。結(jié)果發(fā)現(xiàn)除了地址000000073c800000上分配的3GB堆以外,還有數(shù)量非常多的64M一塊的內(nèi)存段,還有巨量小的物理內(nèi)存塊映射到不同的虛擬內(nèi)存段上。但到現(xiàn)在為止,我們不知道里面的內(nèi)容是什么,是通過什么產(chǎn)生的。
[root]$ pmap -x 75  | sort -n -k3
 
.....省略N行
 
0000000040626000   55488   55484   55484 rwx--    [ anon ]
 
00007fa07c000000   65536   55820   55820 rwx--    [ anon ]
 
00007fa044000000   65536   55896   55896 rwx--    [ anon ]
 
00007fa0c0000000   65536   56304   56304 rwx--    [ anon ]
 
00007f9db8000000   65536   56360   56360 rwx--    [ anon ]
 
00007fa0b8000000   65536   56836   56836 rwx--    [ anon ]
 
00007fa084000000   65536   57916   57916 rwx--    [ anon ]
 
00007f9ec4000000   65532   59752   59752 rwx--    [ anon ]
 
00007fa008000000   65536   60012   60012 rwx--    [ anon ]
 
00007f9e58000000   65536   61608   61608 rwx--    [ anon ]
 
00007f9f18000000   65532   61732   61732 rwx--    [ anon ]
 
00007fa018000000   65532   61928   61928 rwx--    [ anon ]
 
00007fa088000000   65536   62336   62336 rwx--    [ anon ]
 
00007fa020000000   65536   62428   62428 rwx--    [ anon ]
 
00007f9e44000000   65536   64352   64352 rwx--    [ anon ]
 
00007f9ec0000000   65528   64928   64928 rwx--    [ anon ]
 
00007fa050000000   65532   65424   65424 rwx--    [ anon ]
 
00007f9e08000000   65512   65472   65472 rwx--    [ anon ]
 
00007f9de0000000   65524   65512   65512 rwx--    [ anon ]
 
00007f9dec000000   65532   65532   65532 rwx--    [ anon ]
 
00007f9dac000000   65536   65536   65536 rwx--    [ anon ]
 
00007f9dc8000000   65536   65536   65536 rwx--    [ anon ]
 
00007f9e30000000   65536   65536   65536 rwx--    [ anon ]
 
00007f9eb4000000   65536   65536   65536 rwx--    [ anon ]
 
00007fa030000000   65536   65536   65536 rwx--    [ anon ]
 
00007fa0b0000000   65536   65536   65536 rwx--    [ anon ]
 
000000073c800000 3119140 2488596 2487228 rwx--    [ anon ]
 
total kB        17629516 7384476 7377520
通過google,找到以下資料 Linux glibc >= 2.10 (RHEL 6) malloc may show excessive virtual memory usage)
文章指出造成應(yīng)用程序大量申請(qǐng)64M大內(nèi)存塊的原因是由Glibc的一個(gè)版本升級(jí)引起的,通過export MALLOC_ARENA_MAX=4可以解決VSZ占用過高的問題。雖然這也是一個(gè)問題,但卻不是我們想要的,因?yàn)槲覀冊(cè)鲩L(zhǎng)的是物理內(nèi)存,而不是虛擬內(nèi)存。
NMT
幸運(yùn)的是 JDK1.8有Native Memory Tracker可以幫助定位。通過在啟動(dòng)參數(shù)上加入-XX:NativeMemoryTracking=detail就可以啟用。在命令行執(zhí)行jcmd可查看內(nèi)存分配。
#jcmd 75 VM.native_memory summary
 
Native Memory Tracking: Total: reserved=5074027KB, committed=3798707KB -                 Java Heap (reserved=3072000KB, committed=3072000KB)                            (mmap: reserved=3072000KB, committed=3072000KB) -                     Class (reserved=1075949KB, committed=28973KB)                            (classes #4819)                            (malloc=749KB #13158)                            (mmap: reserved=1075200KB, committed=28224KB) -                    Thread (reserved=484222KB, committed=484222KB)                            (thread #470)                            (stack: reserved=482132KB, committed=482132KB)                            (malloc=1541KB #2371)                            (arena=550KB #938) -                      Code (reserved=253414KB, committed=25070KB)                            (malloc=3814KB #5593)                            (mmap: reserved=249600KB, committed=21256KB) -                        GC (reserved=64102KB, committed=64102KB)                            (malloc=54094KB #255)                            (mmap: reserved=10008KB, committed=10008KB) -                  Compiler (reserved=542KB, committed=542KB)                            (malloc=411KB #543)                            (arena=131KB #3) -                  Internal (reserved=50582KB, committed=50582KB)                            (malloc=50550KB #13713)                            (mmap: reserved=32KB, committed=32KB) -                    Symbol (reserved=6384KB, committed=6384KB)                            (malloc=4266KB #31727)                            (arena=2118KB #1) -    Native Memory Tracking (reserved=1325KB, committed=1325KB)                            (malloc=208KB #3083)                            (tracking overhead=1117KB) -               Arena Chunk (reserved=231KB, committed=231KB)                            (malloc=231KB) -                   Unknown (reserved=65276KB, committed=65276KB)                            (mmap: reserved=65276KB, committed=65276KB)
雖然pmap得到的內(nèi)存地址和NMT大體能對(duì)的上,但仍然有不少內(nèi)存去向成謎。雖然是個(gè)好工具但問題并不能解決。
gdb
非常好奇64M或者其他小內(nèi)存塊中是什么內(nèi)容,接下來通過gdbdump出來。讀取/proc目錄下的maps文件,能精準(zhǔn)的知曉目前進(jìn)程的內(nèi)存分布。
以下腳本通過傳入進(jìn)程id,能夠?qū)⑺P(guān)聯(lián)的內(nèi)存全部dump到文件中(會(huì)影響服務(wù),慎用)。
grep rw-p /proc/$1/maps | sed -n 's/^\([0-9a-f]*\)-\([0-9a-f]*\) .*$/\1 \2/p' | while read start stop; do gdb --batch --pid $1 -ex "dump memory $1-$start-$stop.dump 0x$start 0x$stop"; done
更多時(shí)候,推薦之dump一部分內(nèi)存。(再次提醒操作會(huì)影響服務(wù),注意dump的內(nèi)存塊大小,慎用)。
gdb --batch --pid 75 -ex "dump memory a.dump 0x7f2bceda1000 0x7f2bcef2b000
[root]$ du -h *
dump 4.0K
55-00600000-00601000.dump 400K
55-00eb7000-00f1b000.dump 0
55-704800000-7c0352000.dump 47M
55-7f2840000000-7f2842eb8000.dump 53M
55-7f2848000000-7f284b467000.dump 64M
55-7f284c000000-7f284fffa000.dump 64M
55-7f2854000000-7f2857fff000.dump 64M
55-7f285c000000-7f2860000000.dump 64M
55-7f2864000000-7f2867ffd000.dump 1016K
55-7f286a024000-7f286a122000.dump 1016K
55-7f286a62a000-7f286a728000.dump 1016K
55-7f286d559000-7f286d657000.dump
是時(shí)候查看里面的內(nèi)容了
[root]$ view 55-7f284c000000-7f284fffa000.dump
^@^@X+^?^@^@^@^@^@d(^?^@^@^@ ÿ^C^@^@^@^@^@ ÿ^C^@^@^@^@^@^@^@^@^@^@^@^@±<97>p^C^@^@^@^@ 8^^Z+^?^@^@ ^@^@d(^?^@^@ 8^^Z+^?^@^@ ^@^@d(^?^@^@
achine":524993642,"timeSecond":1460272569,"inc":2145712868,"new":false},"device":{"client":"android","uid":"xxxxx","version":881},"
device_android":{"BootSerialno":"xxxxx","CpuInfo":"0-7","MacInfo":"2c:5b:b8:b0:d5:10","RAMSize":"4027212","SdcardInfo":"xxxx","Serialno":"xxxx",
"android_id":"488aedba19097476","buildnumber":"KTU84P/1416486236","device_ip":"0.0.0.0","mac":"2c:5b:b8:b0:d5:10","market_source":"12","model":"OPPO ...more
納尼?這些內(nèi)容不應(yīng)該在堆里面么?為何還會(huì)使用額外的內(nèi)存進(jìn)行分配?上面已經(jīng)排查netty申請(qǐng)directbuffer的原因了,那么還有什么地方在分配堆外內(nèi)存呢?
perf
傳統(tǒng)工具失靈,快到了黔驢技窮的時(shí)候了,是時(shí)候祭出神器perf了。
使用 perf record -g -p 55 開啟監(jiān)控棧函數(shù)調(diào)用。運(yùn)行一段時(shí)間后Ctrl+C結(jié)束,會(huì)生成一個(gè)文件perf.data。
執(zhí)行perf report -i perf.data查看報(bào)告。
如圖,進(jìn)程大量執(zhí)行bzip相關(guān)函數(shù)。搜索zip,結(jié)果如下:
-.-!
進(jìn)程調(diào)用了Java_java_util_zip_Inflater_inflatBytes() 申請(qǐng)了內(nèi)存,僅有一小部分調(diào)用Deflater釋放內(nèi)存。與pmap內(nèi)存地址相比對(duì),確實(shí)是bzip在搞鬼。
原創(chuàng)文章,轉(zhuǎn)載注明出處 (http://sayhiai.com)
解決
java項(xiàng)目搜索zip定位到代碼,發(fā)現(xiàn)確實(shí)有相關(guān)bzip壓縮解壓操作,而且GZIPInputStream有個(gè)地方?jīng)]有close。
GZIPInputStream使用Inflater申請(qǐng)堆外內(nèi)存,Deflater釋放內(nèi)存,調(diào)用close()方法來主動(dòng)釋放。如果忘記關(guān)閉,Inflater對(duì)象的生命會(huì)延續(xù)到下一次GC。在此過程中,堆外內(nèi)存會(huì)一直增長(zhǎng)。
原代碼:
public byte[] decompress ( byte[] input) throws IOException {
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                IOUtils.copy(new GZIPInputStream(new ByteArrayInputStream(input)), out);
                return out.toByteArray();
            }
修改后:
 public byte[] decompress(byte[] input) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        GZIPInputStream gzip = new GZIPInputStream(new ByteArrayInputStream(input));
        IOUtils.copy(gzip, out);
        gzip.close();
        return out.toByteArray();
    }
經(jīng)觀察,問題解決。
--------------------- 
作者:lycyingO 
來源:CSDN 
原文:https://blog.csdn.net/lycyingO/article/details/80854669 
版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請(qǐng)附上博文鏈接!


小馬歌 2019-03-30 11:44 發(fā)表評(píng)論
]]>
POSIX 線程詳解- 一種支持內(nèi)存共享的簡(jiǎn)捷工具【轉(zhuǎn)】http://www.aygfsteel.com/xiaomage234/archive/2019/02/16/433640.html小馬歌小馬歌Sat, 16 Feb 2019 03:37:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2019/02/16/433640.htmlhttp://www.aygfsteel.com/xiaomage234/comments/433640.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2019/02/16/433640.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/433640.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/433640.html閱讀全文

小馬歌 2019-02-16 11:37 發(fā)表評(píng)論
]]>
MySQL加鎖分析【轉(zhuǎn)】http://www.aygfsteel.com/xiaomage234/archive/2019/02/13/433636.html小馬歌小馬歌Wed, 13 Feb 2019 09:07:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2019/02/13/433636.htmlhttp://www.aygfsteel.com/xiaomage234/comments/433636.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2019/02/13/433636.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/433636.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/433636.html閱讀全文

小馬歌 2019-02-13 17:07 發(fā)表評(píng)論
]]>
MySQL 小心使用 replace into【轉(zhuǎn)】http://www.aygfsteel.com/xiaomage234/archive/2018/12/25/433561.html小馬歌小馬歌Tue, 25 Dec 2018 11:19:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2018/12/25/433561.htmlhttp://www.aygfsteel.com/xiaomage234/comments/433561.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2018/12/25/433561.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/433561.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/433561.html摘要: MySQL replace into 錯(cuò)誤案例 背景 * MySQL5.7 * ROW模式 * 表結(jié)構(gòu) CREATE TABLE `test` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `col_1` varc

MySQL replace into 錯(cuò)誤案例

背景

* MySQL5.7  * ROW模式   * 表結(jié)構(gòu) CREATE TABLE `test` (   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,   `col_1` varchar(100) DEFAULT NULL,   `col_2` varchar(100) DEFAULT NULL,   `col_3` varchar(100) DEFAULT NULL,   PRIMARY KEY (`id`),   UNIQUE KEY `col_1` (`col_1`) ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 

錯(cuò)誤場(chǎng)景一

其他字段value莫名其妙的沒了

  • step1 初始化記錄
mater:lc> REPLACE INTO test (col_1,col_2,col_3) values('a','a','a'); Query OK, 1 row affected (0.00 sec) --注意,這里是影響了1條記錄  master:lc> REPLACE INTO test (col_1,col_2,col_3) values('b','b','b'); Query OK, 1 row affected (0.00 sec) --注意,這里是影響了1條記錄  master:lc> REPLACE INTO test (col_1,col_2,col_3) values('c','c','c'); Query OK, 1 row affected (0.00 sec) --注意,這里是影響了1條記錄   master > show create table test  | test  | CREATE TABLE `test` (   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,   `col_1` varchar(100) DEFAULT NULL,   `col_2` varchar(100) DEFAULT NULL,   `col_3` varchar(100) DEFAULT NULL,   PRIMARY KEY (`id`),   UNIQUE KEY `col_1` (`col_1`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 |   mater > select * from test; +----+-------+-------+-------+ | id | col_1 | col_2 | col_3 | +----+-------+-------+-------+ |  1 | a     | a     | a     | |  2 | b     | b     | b     | |  3 | c     | c     | c     | +----+-------+-------+-------+ 3 rows in set (0.00 sec)  
  • step2 構(gòu)造錯(cuò)誤場(chǎng)景
master:lc> replace into test(col_1,col_2) values('c','cc'); Query OK, 2 rows affected (0.00 sec)  dba:lc> select * from test; +----+-------+-------+-------+ | id | col_1 | col_2 | col_3 | +----+-------+-------+-------+ |  1 | a     | a     | a     | |  2 | b     | b     | b     | |  4 | c     | cc    | NULL  | +----+-------+-------+-------+ 3 rows in set (0.00 sec)  
  • 總結(jié)
  1. col_3 的值,從原來的c,變成了NULL,天吶,數(shù)據(jù)不見了。 id 也變了。
  2. 用戶原本的需求,應(yīng)該是如果col_1='c' 存在,那么就改變col_2='cc',其余的記錄保持不變,結(jié)果id,col_3都變化了
  3. 解決方案就是:將replace into 改成 INSERT INTO … ON DUPLICATE KEY UPDATE

但是你以為這樣就完美的解決了嗎? 馬上就會(huì)帶來另外一場(chǎng)災(zāi)難,請(qǐng)看下面的錯(cuò)誤場(chǎng)景

錯(cuò)誤場(chǎng)景二

ERROR 1062 (23000): Duplicate entry 'x' for key 'PRIMARY'

  • step1 初始化記錄
 mater:lc> REPLACE INTO test (col_1,col_2) values('a','a'); Query OK, 1 row affected (0.00 sec) --注意,這里是影響了1條記錄  master:lc> REPLACE INTO test (col_1,col_2) values('b','b'); Query OK, 1 row affected (0.00 sec) --注意,這里是影響了1條記錄  master:lc> REPLACE INTO test (col_1,col_2) values('c','c'); Query OK, 1 row affected (0.00 sec) --注意,這里是影響了1條記錄   master > show create table test  | test  | CREATE TABLE `test` (   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,   `col_1` varchar(100) DEFAULT NULL,   `col_2` varchar(100) DEFAULT NULL,   PRIMARY KEY (`id`),   UNIQUE KEY `col_1` (`col_1`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 |   slave > show create table test  | test  | CREATE TABLE `test` (   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,   `col_1` varchar(100) DEFAULT NULL,   `col_2` varchar(100) DEFAULT NULL,   PRIMARY KEY (`id`),   UNIQUE KEY `col_1` (`col_1`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 |
  • step2 構(gòu)造錯(cuò)誤場(chǎng)景
* master  mater:lc> REPLACE INTO test (col_1,col_2) values('c','cc'); Query OK, 2 rows affected (0.00 sec)  --注意,這里是影響了兩條記錄  mater:lc> show create table test  | test  | CREATE TABLE `test` (   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,   `col_1` varchar(100) DEFAULT NULL,   `col_2` varchar(100) DEFAULT NULL,   PRIMARY KEY (`id`),   UNIQUE KEY `col_1` (`col_1`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 |  master:lc> select * from test +----+-------+-------+ | id | col_1 | col_2 | +----+-------+-------+ |  1 | a     | a     | |  2 | b     | b     | |  4 | c     | cc    | +----+-------+-------+ 3 rows in set (0.00 sec)  * slave  slave:lc> show create table test  | test  | CREATE TABLE `test` (   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,   `col_1` varchar(100) DEFAULT NULL,   `col_2` varchar(100) DEFAULT NULL,   PRIMARY KEY (`id`),   UNIQUE KEY `col_1` (`col_1`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 |  slave:lc> select * from test +----+-------+-------+ | id | col_1 | col_2 | +----+-------+-------+ |  1 | a     | a     | |  2 | b     | b     | |  4 | c     | cc    | +----+-------+-------+ 3 rows in set (0.00 sec) 
  • step3 錯(cuò)誤案例產(chǎn)生
* 假設(shè)有一天,master 掛了, 由slave 提升為 new mater  原slave:lc> show create table test  | test  | CREATE TABLE `test` (   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,   `col_1` varchar(100) DEFAULT NULL,   `col_2` varchar(100) DEFAULT NULL,   PRIMARY KEY (`id`),   UNIQUE KEY `col_1` (`col_1`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 |  原slave:lc> select * from test +----+-------+-------+ | id | col_1 | col_2 | +----+-------+-------+ |  1 | a     | a     | |  2 | b     | b     | |  4 | c     | cc    | +----+-------+-------+ 3 rows in set (0.00 sec)   ===注意==  root:lc> REPLACE INTO test (col_1,col_2) values('d','d'); ERROR 1062 (23000): Duplicate entry '4' for key 'PRIMARY'  
  • 總結(jié)
* Row 模式,主從情況下,replace into 和 INSERT INTO … ON DUPLICATE KEY UPDATE 都會(huì)導(dǎo)致以上問題的發(fā)生 * 解決方案: 最后可以通過alter table auto_increment值解決,但是這樣已經(jīng)造成mater的表很長(zhǎng)時(shí)間沒有寫入了。。。

最后總結(jié)

  • replace with unique key
1. 禁止 replace into (錯(cuò)誤一,錯(cuò)誤二 都會(huì)發(fā)生) 2. 禁止 INSERT INTOON DUPLICATE KEY UPDATE (錯(cuò)誤二 會(huì)發(fā)生)
  • replace with primary key
1. 禁止 replace into (會(huì)發(fā)生錯(cuò)誤場(chǎng)景一的案例,丟失部分字段數(shù)據(jù)) 2. 可以使用INSERT INTOON DUPLICATE KEY UPDATE 代替 replace into


小馬歌 2018-12-25 19:19 發(fā)表評(píng)論
]]>
MySQL 開發(fā)實(shí)踐 8 問,你能 hold 住幾個(gè)?【轉(zhuǎn)】http://www.aygfsteel.com/xiaomage234/archive/2018/12/03/433534.html小馬歌小馬歌Mon, 03 Dec 2018 07:55:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2018/12/03/433534.htmlhttp://www.aygfsteel.com/xiaomage234/comments/433534.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2018/12/03/433534.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/433534.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/433534.html閱讀全文

小馬歌 2018-12-03 15:55 發(fā)表評(píng)論
]]>
主站蜘蛛池模板: 安陆市| 开封市| 曲阳县| 炎陵县| 云龙县| 长汀县| 岚皋县| 和龙市| 南木林县| 鹤庆县| 柏乡县| 大丰市| 永春县| 东源县| 江华| 右玉县| 保德县| 客服| 唐山市| 石景山区| 皋兰县| 资源县| 全椒县| 蚌埠市| 克什克腾旗| 二连浩特市| 视频| 两当县| 华阴市| 三台县| 达拉特旗| 墨竹工卡县| 延津县| 祥云县| 海宁市| 兴业县| 阿尔山市| 长岛县| 阳谷县| 安龙县| 灵台县|