江苏快三开奖结果

隨筆 - 93  文章 - 0  trackbacks - 0

1.何為隊列

TINGDAODUILIEXIANGXINDAJIADUIQIBINGBUMOSHENG,ZAIWOMENXIANSHISHENGHUOZHONGDUILIESUICHUKEJIAN,QUCHAOSHIJIEZHANG,NIHUIKANJIANDAJIADOUHUIYIPAIPAIDEZHANDEHAOHAODE,DENGDAIJIEZHANG,WEISHENMEYAOZHANDEYIPAIPAIDE,NIXIANGXIANGYIXIADAJIADOUMEIYOUSUZHI,YIWOFENGDESHANGQUJIEZHANG,BUJINRANGZHEGECHAOSHIBENGKUI,HUANHUIRONGYIZAOCHENGGEZHONGCAITASHIJIAN,DANGRANZHEXIESHIQISHIZAIWOMENXIANSHIZHONGYESHIHUIJINGCHANGFASHENG。

江苏快三开奖结果DANGRANZAIJISUANJISHIJIEZHONG,DUILIESHISHUYUYIZHONGSHUJUJIEGOU,DUILIECAIYONGDEFIFO(first in firstout),XINYUANSU(DENGDAIJINRUDUILIEDEYUANSU)ZONGSHIBEICHARUDAOWEIBU,ERDUQUDESHIHOUZONGSHICONGTOUBUKAISHIDUQU。ZAIJISUANZHONGDUILIEYIBANYONGLAIZUOPAIDUI(RUXIANCHENGCHIDEDENGDAIPAIDUI,SUODEDENGDAIPAIDUI),YONGLAIZUOJIEOU(SHENGCHANZHEXIAOFEIZHEMOSHI),YIBUDENGDENG。

2.jdk中的隊列

ZAIjdkZHONGDEDUILIEDOUSHIXIANLEjava.util.QueueJIEKOU,ZAIDUILIEZHONGYOUFENWEILIANGLEI,YILEISHIXIANCHENGBUANQUANDE,ArrayDeque,LinkedListDENGDENG,HUANYOUYILEIDOUZAIjava.util.concurrentBAOXIASHUYUXIANCHENGANQUAN,ERZAIWOMENZHENSHIDEHUANJINGZHONG,WOMENDEJIQIDOUSHISHUYUDUOXIANCHENG,DANGDUOXIANCHENGDUITONGYIGEDUILIEJINXINGPAIDUICAOZUODESHIHOU,RUGUOSHIYONGXIANCHENGBUANQUANHUICHUXIAN,FUGAISHUJU,SHUJUDIUSHIDENGWUFAYUCEDESHIQING,SUOYIWOMENZHEGESHIHOUZHINENGXUANZEXIANCHENGANQUANDEDUILIE。ZAIjdkZHONGTIGONGDEXIANCHENGANQUANDEDUILIEXIAMIANJIANDANLIEJUBUFENDUILIE:

隊列名字 是否加鎖 數據結構 關鍵技術點 是否有鎖 是否有界
ArrayBlockingQueue 數組array ReentrantLock 有鎖 有界
LinkedBlockingQueue 鏈表 ReentrantLock 有鎖 有界
LinkedTransferQueue 鏈表 CAS 無鎖 無界
ConcurrentLinkedQueue 鏈表 CAS 無鎖 無界

WOMENKEYIKANJIAN,WOMENWUSUODEDUILIESHIWUJIEDE,YOUSUODEDUILIESHIYOUJIEDE,ZHELIJIUHUISHEJIDAOYIGEWENTI,WOMENZAIZHENZHENGDEXIANSHANGHUANJINGZHONG,WUJIEDEDUILIE,DUIWOMENXITONGDEYINGXIANGBIJIAODA,YOUKENENGHUIDAOZHIWOMENNEICUNZHIJIEYICHU,SUOYIWOMENSHOUXIANDEPAICHUWUJIEDUILIE,DANGRANBINGBUSHIWUJIEDUILIEJIUMEIYONGLE,ZHISHIZAIMOUXIECHANGJINGXIADEPAICHU。QICIHUANSHENGXIAArrayBlockingQueue,LinkedBlockingQueueLIANGGEDUILIE,TAMENLIANGGEDOUSHIYONGReentrantLockKONGZHIDEXIANCHENGANQUAN,TAMENLIANGGEDEQUBIEYIGESHISHUZU,YIGESHILIANBIAO,ZAIDUILIEZHONG,YIBANHUOQUZHEGEDUILIEYUANSUZHIHOUJINJIEZHUHUIHUOQUXIAYIGEYUANSU,HUOZHEYICIHUOQUDUOGEDUILIEYUANSUDOUYOUKENENG,ERSHUZUZAINEICUNZHONGDIZHISHILIANXUDE,ZAICAOZUOXITONGZHONGHUIYOUHUANCUNDEYOUHUA(XIAMIANYEHUIJIESHAOHUANCUNXING),SUOYIFANGWENDESUDUHUILVESHENGYICHOU,WOMENYEHUIJINLIANGQUXUANZEArrayBlockingQueue。ERSHISHIZHENGMINGZAIHENDUODISANFANGDEKUANGJIAZHONG,BIRUZAOQIDElog4jYIBU,DOUSHIXUANZEDEArrayBlockingQueue。

江苏快三开奖结果DANGRANArrayBlockingQueue,YEYOUZIJIDEBIDUAN,JIUSHIXINGNENGBIJIAODI,WEISHENMEjdkHUIZENGJIAYIXIEWUSUODEDUILIE,QISHIJIUSHIWEILEZENGJIAXINGNENG,HENKUNAO,YOUXUYAOWUSUO,YOUXUYAOYOUJIE,ZHEGESHIHOUKONGPAHUIRENBUZHUSHUOYIJUNIZABUSHANGTIANNI?DANSHIHUANZHENYOURENSHANGTIANLE。

3.Disruptor

DisruptorJIUSHISHANGMIANSHUODENEIGETIAN,DisruptorSHIYINGGUOWAIHUIJIAOYIGONGSILMAXKAIFADEYIGEGAOXINGNENGDUILIE,BINGQIESHIYIGEKAIYUANDEBINGFAKUANGJIA,BINGHUODE2011Duke’sCHENGXUKUANGJIACHUANGXINJIANG。NENGGOUZAIWUSUODEQINGKUANGXIASHIXIANWANGLUODEQueueBINGFACAOZUO,JIYUDisruptorKAIFADEXITONGDANXIANCHENGNENGZHICHENGMEIMIAO600WANDINGDAN。MUQIAN,BAOKUOApache Storm、Camel、Log4j2DENGDENGZHIMINGDEKUANGJIADOUZAINEIBUJICHENGLEDisruptorYONGLAITIDAIjdkDEDUILIE,YICILAIHUODEGAOXINGNENG。

3.1為什么這么牛逼?

江苏快三开奖结果SHANGMIANYIJINGBADisruptorCHUICHULEHUALE,NIKENDINGHUICHANSHENGYIWEN,TAZHENDENENGYOUZHEMENIUBIMA,WODEHUIDASHIDANGRANDE,ZAIDisruptorZHONGYOUSANDASHAQI:

  • CAS
  • 消除偽共享
  • RingBuffer 有了這三大殺器,Disruptor才變得如此牛逼。

3.1.1鎖和CAS

江苏快三开奖结果WOMENArrayBlockingQueueWEISHENMEHUIBEIPAOQIDEYIDIAN,JIUSHIYINWEIYONGLEZHONGLIANGJIlockSUO,ZAIWOMENJIASUOGUOCHENGZHONGWOMENHUIBASUOGUAQI,JIESUOHOU,YOUHUIBAXIANCHENGHUIFU,ZHEYIGUOCHENGHUIYOUYIDINGDEKAIXIAO,BINGQIEWOMENYIDANMEIYOUHUOQUSUO,ZHEGEXIANCHENGJIUZHINENGYIZHIDENGDAI,ZHEGEXIANCHENGSHENMESHIYEBUNENGZUO。

CAS(compare and swap),GUMINGSIYIXIANBIJIAOZAIJIAOHUAN,YIBANSHIBIJIAOSHIFOUSHILAODEZHI,RUGUOSHIDEJINXINGJIAOHUANSHEZHI,DAJIASHUXILEGUANSUODERENDOUZHIDAOCASKEYIYONGLAISHIXIANLEGUANSUO,CASZHONGMEIYOUXIANCHENGDESHANGXIAWENQIEHUAN,JIANSHAOLEBUBIYAODEKAIXIAO。 ZHELISHIYONGJMH,YONGLIANGGEXIANCHENG,MEICI1YICIDIAOYONG,ZAIWOBENJISHANGJINXINGCESHI,DAIMARUXIA:

@BenchmarkMode({Mode.SampleTime}) @OutputTimeUnit(TimeUnit.MILLISECONDS) @Warmup(iterations=3, time = 5, timeUnit = TimeUnit.MILLISECONDS) @Measurement(iterations=1,batchSize = 100000000) @Threads(2) @Fork(1) @State(Scope.Benchmark) public class Myclass {     Lock lock = new ReentrantLock();     long i = 0;     AtomicLong atomicLong = new AtomicLong(0);     @Benchmark     public void measureLock() {         lock.lock();         i++;         lock.unlock();     }     @Benchmark     public void measureCAS() {         atomicLong.incrementAndGet();     }     @Benchmark     public void measureNoLock() {         i++;     } } 復制代碼

CESHICHULAIJIEGUORUXIA:

測試項目 測試結果
Lock 26000ms
CAS 4840ms
無鎖 197ms

KEYIKANJIANLockSHIWUWEISHU,CASSHISIWEISHU,WUSUOGENGXIAOSHISANWEISHU。 YOUCIWOMENKEYIZHIDAOLock>CAS>WUSUO。

江苏快三开奖结果ERWOMENDEDisruptorZHONGSHIYONGDEJIUSHICAS,TALIYONGCASJINXINGDUILIEZHONGDEYIXIEXIABIAOSHEZHI,JIANSHAOLESUODECHONGTU,TIGAOLEXINGNENG。

LINGWAIDUIYUjdkZHONGQITADEWUSUODUILIEYESHISHIYONGCAS,YUANZILEIYESHISHIYONGCAS。

3.1.2偽共享

TANDAOLEWEIGONGXIANGJIUBUDEBUSHUOJISUANJICPUHUANCUN,HUANCUNDAXIAOSHICPUDEZHONGYAOZHIBIAOZHIYI,ERQIEHUANCUNDEJIEGOUHEDAXIAODUICPUSUDUDEYINGXIANGFEICHANGDA,CPUNEIHUANCUNDEYUNXINGPINLVJIGAO,YIBANSHIHECHULIQITONGPINYUNZUO,GONGZUOXIAOLVYUANYUANDAYUXITONGNEICUNHEYINGPAN。SHIJIGONGZUOSHI,CPUWANGWANGXUYAOZHONGFUDUQUTONGYANGDESHUJUKUAI,ERHUANCUNRONGLIANGDEZENGDA,KEYIDAFUDUTISHENGCPUNEIBUDUQUSHUJUDEMINGZHONGLV,ERBUYONGZAIDAONEICUNHUOZHEYINGPANSHANGXUNZHAO,YICITIGAOXITONGXINGNENG。DANSHICONGCPUXINPIANMIANJIHECHENGBENDEYINSULAIKAOLV,HUANCUNDOUHENXIAO。

 

 

CPUHUANCUNKEYIFENWEIYIJIHUANCUN,ERJIHUANCUN,RUJINZHULIUCPUHUANYOUSANJIHUANCUN,SHENZHIYOUXIECPUHUANYOUSIJIHUANCUN。MEIYIJIHUANCUNZHONGSUOCHUCUNDEQUANBUSHUJUDOUSHIXIAYIJIHUANCUNDEYIBUFEN,ZHESANZHONGHUANCUNDEJISHUNANDUHEZHIZAOCHENGBENSHIXIANGDUIDIJIANDE,SUOYIQIRONGLIANGYESHIXIANGDUIDIZENGDE。

WEISHENMECPUHUIYOUL1、L2、L3ZHEYANGDEHUANCUNSHEJI?ZHUYAOSHIYINWEIXIANZAIDECHULIQITAIKUAILE,ERCONGNEICUNZHONGDUQUSHUJUSHIZAITAIMAN(YIGESHIYINWEINEICUNBENSHENSUDUBUGOU,LINGYIGESHIYINWEITALICPUTAIYUANLE,ZONGDELAISHUOXUYAORANGCPUDENGDAIJISHISHENZHIJIBAIGESHIZHONGZHOUQI),ZHEGESHIHOUWEILEBAOZHENGCPUDESUDU,JIUXUYAOYANCHIGENGXIAOSUDUGENGKUAIDENEICUNTIGONGBANGZHU,ERZHEJIUSHIHUANCUN。DUIZHEGEGANXINGQUKEYIBADIANNAOCPUCHAIXIALAI,ZIJIBAWANYIXIA。

江苏快三开奖结果MEIYICINITINGJIANintelFABUXINDEcpuSHENME,BIRUi7-7700k,8700k,DOUHUIDUIcpuHUANCUNDAXIAOJINXINGYOUHUA,GANXINGQUKEYIZIXINGXIALAISOUSUO,ZHEXIEDEFABUHUIHUOZHEFABUWENZHANG。

MartinHEMikeDE QConpresentationYANJIANGZHONGGEICHULEYIXIEMEIGEHUANCUNSHIJIAN:

從CPU到 大約需要的CPU周期 大約需要的時間
主存 約60-80納秒
QPI 總線傳輸(between sockets, not drawn) 約20ns
L3 cache 約40-45 cycles 約15ns
L2 cache 約10 cycles 約3ns
L1 cache 約3-4 cycles 約1ns
寄存器 1 cycle

緩存行

江苏快三开奖结果ZAIcpuDEDUOJIHUANCUNZHONG,BINGBUSHIYIDULIDEXIANGLAIBAOCUNDE,ERSHILEISIYIZHONGpageCaheDEYIZHONGCELVE,YIHUANCUNXINGLAIBAOCUN,ERHUANCUNXINGDEDAXIAOTONGCHANGSHI64ZIJIE,ZAIJavaZHONGLongSHI8GEZIJIE,SUOYIKEYICUNCHU8GELong,JUGELIZI,NIFANGWENYIGElongDEBIANLIANGDESHIHOU,TAHUIBABANGZHUZAIJIAZAI7GE,WOMENSHANGMIANSHUOWEISHENMEXUANZESHUZUBUXUANZELIANBIAO,YEJIUSHIZHEGEYUANYIN,ZAISHUZUZHONGKEYIYIKAOHUANCHONGXINGDEDAOHENKUAIDEFANGWEN。

 

HUANCUNXINGSHIWANNENGDEMA?NO,YINWEITAYIRANDAILAILEYIGEQUEDIAN,WOZAIZHELIJUGELIZISHUOMINGZHEGEQUEDIAN,KEYIXIANGXIANGYOUGESHUZUDUILIE,ArrayQueue,TADESHUJUJIEGOURUXIA:

class ArrayQueue{     long maxSize;     long currentIndex; } 復制代碼

DUIYUmaxSizeSHIWOMENYIKAISHIJIUDINGYIHAODE,SHUZUDEDAXIAO,DUIYUcurrentIndex,SHIBIAOZHIWOMENDANGQIANDUILIEDEWEIZHI,ZHEGEBIANHUABIJIAOKUAI,KEYIXIANGXIANGNIFANGWENmaxSizeDESHIHOU,SHIBUSHIBAcurrentIndexYEJIAZAIJINLAILE,ZHEGESHIHOU,QITAXIANCHENGGENGXINcurrentIndex,JIUHUIBAcpuZHONGDEHUANCUNXINGZHIWEIWUXIAO,QINGZHUYIZHESHICPUGUIDINGDE,TABINGBUSHIZHIBAcurrentIndexZHIWEIWUXIAO,RUGUOCISHIYOUJIXUFANGWENmaxSizeTAYIRANDEJIXUCONGNEICUNZHONGDUQU,DANSHIMaxSizeQUESHIWOMENYIKAISHIDINGYIHAODE,WOMENYINGGAIFANGWENHUANCUNJIKE,DANSHIQUEBEIWOMENJINGCHANGGAIBIANDEcurrentIndexSUOYINGXIANG。

 

 

Padding的魔法

江苏快三开奖结果WEILEJIEJUESHANGMIANHUANCUNXINGCHUXIANDEWENTI,ZAIDisruptorZHONGCAIYONGLEPaddingDEFANGSHI,

class LhsPadding {     protected long p1, p2, p3, p4, p5, p6, p7; }  class Value extends LhsPadding {     protected volatile long value; }  class RhsPadding extends Value {     protected long p9, p10, p11, p12, p13, p14, p15; } 復制代碼

江苏快三开奖结果QIZHONGDEValueJIUBEIQITAYIXIEWUYONGDElongBIANLIANGGEITIANCHONGLE。ZHEYANGNIXIUGAIValueDESHIHOU,JIUBUHUIYINGXIANGDAOQITABIANLIANGDEHUANCUNXING。

ZUIHOUSHUNBIANYITI,ZAIjdk8ZHONGTIGONGLE@ContendedDEZHUJIE,DANGRANYIBANLAISHUOZHIYUNXUJdkZHONGNEIBU,RUGUONIZIJISHIYONGNEIJIUDEPEIZHIJvmCANSHU -RestricContentended = fase,JIANGXIANZHIZHEGEZHUJIEZHIWEIQUXIAO。HENDUOWENZHANGFENXILEConcurrentHashMap,DANSHIDOUBAZHEGEZHUJIEGEIHULVEDIAOLE,ZAIConcurrentHashMapZHONGJIUSHIYONGLEZHEGEZHUJIE,ZAIConcurrentHashMapMEIGETONGDOUSHIDANDUDEYONGJISHUQIQUZUOJISUAN,ERZHEGEJISHUQIYOUYUSHIKEDOUZAIBIANHUA,SUOYIBEIYONGZHEGEZHUJIEJINXINGTIANCHONGHUANCUNXINGYOUHUA,YICILAIZENGJIAXINGNENG。

 

 

3.1.3RingBuffer

ZAIDisruptorZHONGCAIYONGLESHUZUDEFANGSHIBAOCUNLEWOMENDESHUJU,SHANGMIANWOMENYEJIESHAOLECAIYONGSHUZUBAOCUNWOMENFANGWENSHIHENHAODELIYONGHUANCUN,DANSHIZAIDisruptorZHONGJINYIBUXUANZECAIYONGLEHUANXINGSHUZUJINXINGBAOCUNSHUJU,YEJIUSHIRingBuffer。ZAIZHELIXIANSHUOMINGYIXIAHUANXINGSHUZUBINGBUSHIZHENZHENGDEHUANXINGSHUZU,ZAIRingBufferZHONGSHICAIYONGQUYUDEFANGSHIJINXINGFANGWENDE,BIRUSHUZUDAXIAOWEI 10,0FANGWENDESHISHUZUXIABIAOWEI0ZHEGEWEIZHI,QISHI10,20DENGFANGWENDEYESHISHUZUDEXIABIAOWEI0DEZHEGEWEIZHI。

SHIJISHANG,ZAIZHEXIEKUANGJIAZHONGQUYUBINGBUSHISHIYONG%YUNSUAN,DOUSHISHIYONGDE&YUYUNSUAN,ZHEJIUYAOQIUNISHEZHIDEDAXIAOYIBANSHI2DENCIFANGYEJIUSHI,10,100,1000DENGDENG,ZHEYANGJIANQU1DEHUAJIUSHI,1,11,111,JIUNENGHENHAODESHIYONGindex & (size -1),ZHEYANGLIYONGWEIYUNSUANJIUZENGJIALEFANGWENSUDU。 RUGUOZAIDisruptorZHONGNIBUYONG2DENCIFANGJINXINGDAXIAOSHEZHI,TAHUIPAOCHUbuffersizeBIXUWEI2DENCIFANGYICHANG。

DANGRANQIBUJINJIEJUELESHUZUKUAISUFANGWENDEWENTI,YEJIEJUELEBUXUYAOZAICIFENPEINEICUNDEWENTI,JIANSHAOLELAJIHUISHOU,YINWEIWOMEN0,10,20DENGDOUSHIZHIXINGDETONGYIPIANNEICUNQUYU,ZHEYANGJIUBUXUYAOZAICIFENPEINEICUN,PINFANDEBEIJVMLAJIHUISHOUQIHUISHOU。

 

 

ZICISANDASHAQIYIJINGSHUOWANLE,YOULEZHESANDASHAQIWEIDisruptorRUCIGAOXINGNENGDIANDINGLEJICHU。JIEXIALAIHUANHUIZAIJIANGJIERUHESHIYONGDisruptorHEDisruptorDEJUTIDEGONGZUOYUANLI。

3.2Disruptor怎么使用

XIAMIANJULEYIGEJIANDANDELIZI:

ublic static void main(String[] args) throws Exception {         // 隊列中的元素         class Element {             @Contended             private String value;               public String getValue() {                 return value;             }              public void setValue(String value) {                 this.value = value;             }         }          // 生產者的線程工廠         ThreadFactory threadFactory = new ThreadFactory() {             int i = 0;             @Override             public Thread newThread(Runnable r) {                 return new Thread(r, "simpleThread" + String.valueOf(i++));             }         };          // RingBuffer生產工廠,初始化RingBuffer的時候使用         EventFactory<Element> factory = new EventFactory<Element>() {             @Override             public Element newInstance() {                 return new Element();             }         };          // 處理Event的handler         EventHandler<Element> handler = new EventHandler<Element>() {             @Override             public void onEvent(Element element, long sequence, boolean endOfBatch) throws InterruptedException {                 System.out.println("Element: " + Thread.currentThread().getName() + ": " + element.getValue() + ": " + sequence); //                Thread.sleep(10000000);             }         };           // 阻塞策略         BlockingWaitStrategy strategy = new BlockingWaitStrategy();          // 指定RingBuffer的大小         int bufferSize = 8;          // 創建disruptor,采用單生產者模式         Disruptor<Element> disruptor = new Disruptor(factory, bufferSize, threadFactory, ProducerType.SINGLE, strategy);          // 設置EventHandler         disruptor.handleEventsWith(handler);          // 啟動disruptor的線程         disruptor.start();         for (int i = 0; i < 10; i++) {             disruptor.publishEvent((element, sequence) -> {                 System.out.println("之前的數據" + element.getValue() + "當前的sequence" + sequence);                 element.setValue("我是第" + sequence + "個");             });          }     } 復制代碼

江苏快三开奖结果ZAIDisruptorZHONGYOUJIGEBIJIAOGUANJIANDE: ThreadFactory:ZHESHIYIGEXIANCHENGGONGCHANG,YONGYUWOMENDisruptorZHONGSHENGCHANZHEXIAOFEIDESHIHOUXUYAODEXIANCHENG。 EventFactory:SHIJIANGONGCHANG,YONGYUCHANSHENGWOMENDUILIEYUANSUDEGONGCHANG,ZAIDisruptorZHONG,TAHUIZAICHUSHIHUADESHIHOUZHIJIETIANCHONGMANRingBuffer,YICIDAOWEI。 EventHandler:YONGYUCHULIEventDEhandler,ZHELIYIGEEventHandlerKEYIKANZUOSHIYIGEXIAOFEIZHE,DANSHIDUOGEEventHandlerTAMENDOUSHIDULIXIAOFEIDEDUILIE。 WorkHandler:YESHIYONGYUCHULIEventDEhandler,HESHANGMIANQUBIEZAIYU,DUOGEXIAOFEIZHEDOUSHIGONGXIANGTONGYIGEDUILIE。 WaitStrategy:DENGDAICELVE,ZAIDisruptorZHONGYOUDUOZHONGCELVE,LAIJUEDINGXIAOFEIZHEHUOXIAOFEISHI,RUGUOMEIYOUSHUJUCAIQUDECELVESHISHENME?XIAMIANJIANDANLIEJUYIXIADisruptorZHONGDEBUFENCELVE

  • 江苏快三开奖结果BlockingWaitStrategy:TONGGUOXIANCHENGZUSAIDEFANGSHI,DENGDAISHENGCHANZHEHUANXING,BEIHUANXINGHOU,ZAIXUNHUANJIANCHAYILAIDEsequenceSHIFOUYIJINGXIAOFEI。

  • BusySpinWaitStrategy:XIANCHENGYIZHIZIXUANDENGDAI,KENENGBIJIAOHAOcpu

  • LiteBlockingWaitStrategy:XIANCHENGZUSAIDENGDAISHENGCHANZHEHUANXING,YUBlockingWaitStrategyXIANGBI,QUBIEZAIsignalNeeded.getAndSet,RUGUOLIANGGEXIANCHENGTONGSHIFANGWENYIGEFANGWENwaitfor,YIGEFANGWENsignalAllSHI,KEYIJIANSHAOlockJIASUOCISHU.

  • LiteTimeoutBlockingWaitStrategy:YULiteBlockingWaitStrategyXIANGBI,SHEZHILEZUSAISHIJIAN,CHAOGUOSHIJIANHOUPAOYICHANG。

  • YieldingWaitStrategy:CHANGSHI100CI,RANHOUThread.yield()RANGCHUcpu

江苏快三开奖结果EventTranslator:SHIXIANZHEGEJIEKOUKEYIJIANGWOMENDEQITASHUJUJIEGOUZHUANHUANWEIZAIDisruptorZHONGLIUTONGDEEvent。

3.3工作原理

SHANGMIANYIJINGJIESHAOLECAS,JIANSHAOWEIGONGXIANG,RingBufferSANDASHAQI,JIESHAOXIALAISHUOYIXIADisruptorZHONGSHENGCHANZHEHEXIAOFEIZHEDEZHENGGELIUCHENG。

3.3.1生產者

江苏快三开奖结果DUIYUSHENGCHANZHELAISHUO,KEYIFENWEIDUOSHENGCHANZHEHEDANSHENGCHANZHE,YONGProducerType.Single,HEProducerType.MULTIQUFEN,DUOSHENGCHANZHEHEDANSHENGCHANZHELAISHUODUOLECAS,YINWEIDANSHENGCHANZHEYOUYUSHIDANXIANCHENG,SUOYIBUXUYAOBAOZHENGXIANCHENGANQUAN。

ZAIdisruptorZHONGTONGCHANGYONGdisruptor.publishEventHEdisruptor.publishEvents()JINXINGDANFAHEQUNFA。

ZAIdisruptorFABUYIGESHIJIANJINRUDUILIEXUYAOXIAMIANJIGEBUZOU:

  1. 首先獲取RingBuffer中下一個在RingBuffer上可以發布的位置,這個可以分為兩類:
  • 從來沒有寫過的位置
  • 已經被所有消費者讀過,可以在寫的位置。 如果沒有讀取到會一直嘗試去讀,disruptor做的很巧妙,并沒有一直占據CPU,而是通過LockSuport.park(),進行了一下將線程阻塞掛起操作,為的是不讓CPU一直進行這種空循環,不然其他線程都搶不到CPU時間片。
    獲取位置之后會進行cas進行搶占,如果是單線程就不需要。
  1. 接下來調用我們上面所介紹的EventTranslator將第一步中RingBuffer中那個位置的event交給EventTranslator進行重寫。
  2. 進行發布,在disruptor還有一個額外的數組用來記錄當前ringBuffer所在位置目前最新的序列號是多少,拿上面那個0,10,20舉例,寫到10的時候這個avliableBuffer就在對應的位置上記錄目前這個是屬于10,有什么用呢后面會介紹。進行發布的時候需要更新這個avliableBuffer,然后進行喚醒所有阻塞的生產者。

XIAMIANJIANDANHUAYIXIALIUCHENG,SHANGMIANWOMENNA10JULISHIBUDUIDE,YINWEIbufferSizeBIXUYAO2DENCIFANG,SUOYIWOMENZHELINABuffersize=8LAIJULI:XIAMIANJIESHAOLEDANGWOMENYIJINGpushLE8GEeventYEJIUSHIYIQUANDESHIHOU,JIEXIALAIZAIpush 3TIAOXIAOXIDEYIXIEGUOCHENG: 1.SHOUXIANDIAOYONGnext(3),WOMENDANGQIANZAI7ZHEGEWEIZHISHANGSUOYIJIEXIALAISANTIAOSHI8,9,10,QUYUYEJIUSHI0,1,2。 2.ZHONGXIE0,1,2ZHESANGENEICUNQUYUDESHUJU。 3.XIEavaliableBuffer。

 

 

DUILEBUZHIDAODAJIADUISHANGSHULIUCHENGSHIBUSHIHENSHUXINI,DUIDENEIJIUSHILEISIWOMENDE2PC,LIANGJIEDUANTIJIAO,XIANJINXINGRingBufferDEWEIZHISUODING,RANHOUZAIJINXINGTIJIAOHETONGZHIXIAOFEIZHE。JUTI2PCDEJIESHAOKEYICANZHAOWODELINGWAIYIPIANWENZHANG。

3.3.1消費者

江苏快三开奖结果DUIYUXIAOFEIZHELAISHUO,SHANGMIANJIESHAOLEFENWEILIANGZHONG,YIZHONGSHIDUOGEXIAOFEIZHEDULIXIAOFEI,YIZHONGSHIDUOGEXIAOFEIZHEXIAOFEITONGYIGEDUILIE,ZHELIJIESHAOYIXIAJIAOWEIFUZADEDUOGEXIAOFEIZHEXIAOFEITONGYIGEDUILIE,NENGLIJIEZHEGEYEJIUNENGLIJIEDULIXIAOFEI。 ZAIWOMENDEdisruptor.strat()FANGFAZHONGHUIQIDONGWOMENDEXIAOFEIZHEXIANCHENGYICILAIJINXINGHOUTAIXIAOFEI。ZAIXIAOFEIZHEZHONGYOULIANGGEDUILIEXUYAOWOMENGUANZHU,YIGESHISUOYOUXIAOFEIZHEGONGXIANGDEJINDUDUILIE,HUANYOUGESHIMEIGEXIAOFEIZHEDULIXIAOFEIJINDUDUILIE。 1.DUIXIAOFEIZHEGONGXIANGDUILIEJINXINGXIAYIGENextDECASQIANGZHAN,YIJIDUIZIJIXIAOFEIJINDUDEDUILIEBIAOJIDANGQIANJINDU。 2.WEIZIJISHENQINGKEDUDERingBufferDENextWEIZHI,ZHELIDESHENQINGBUJINJINSHISHENQINGDAOnext,YOUKENENGHUISHENQINGDAOBINextDADEYIGEFANWEI,ZUSAICELVEDESHENQINGDEGUOCHENGRUXIA:

  • 獲取生產者對RingBuffer最新寫的位置
  • 判斷其是否小于我要申請讀的位置
  • 如果大于則證明這個位置已經寫了,返回給生產者。
  • 如果小于證明還沒有寫到這個位置,在阻塞策略中會進行阻塞,其會在生產者提交階段進行喚醒。 3.對這個位置進行可讀校驗,因為你申請的位置可能是連續的,比如生產者目前在7,接下來申請讀,如果消費者已經把8和10這個序列號的位置寫進去了,但是9這個位置還沒來得及寫入,由于第一步會返回10,但是9其實是不能讀的,所以得把位置向下收縮到8。
    4.如果收縮完了之后比當前next要小,則繼續循環申請。 5.交給handler.onEvent()處理

YIYANGDEWOMENJUGELIZI,WOMENYAOSHENQINGnext=8ZHEGEWEIZHI。 1.SHOUXIANZAIGONGXIANGDUILIEQIANGZHANJINDU8,ZAIDULIDUILIEXIERUJINDU7 2.HUOQU8DEKEDUDEZUIDAWEIZHI,ZHELIGENJUBUTONGDECELVEJINXING,WOMENXUANZEZUSAI,YOUYUSHENGCHANZHESHENGCHANLE8,9,10,SUOYIFANHUIDESHI10,ZHEYANGHEHOUXUJIUBUXUYAOZAICIHEavaliableBufferJINXINGDUIBILE。 3.ZUIHOUJIAOGEIhandlerJINXINGCHULI。

 

4.Log4j中的Disruptor

XIAMIANDETUZHANXIANLELog4jSHIYONGDisruptor,ArrayBlockingQueueYIJITONGBUDELog4jTUNTULIANGDEDUIBI,KEYIKANJIANSHIYONGLEDisruptorWANBAOLEQITADE,DANGRANHUANYOUGENGDUODEKUANGJIASHIYONGLEDisruptor,ZHELIJIUBUZUOJIESHAOLE。

 

 


作者:咖啡拿鐵
鏈接:http://juejin.im/post/5b5f10d65188251ad06b78e3
來源:掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
posted @ 2020-01-16 20:12 長戟十三千 閱讀(4) | 評論 (0)編輯 收藏
共享內存實現跨進程消息隊列:《UNIX網絡編程卷2》,消息隊列,p85
虛擬實時:《linux內核設計與實現》, 進程調度,p43
等待隊列:《linux內核設計與實現》, 進程調度,p50
epoll源碼:自旋鎖+就緒隊列,mutex+紅黑樹數據
無限法則服務器:接口->協程+rpc->服務組件, 可灰更微服務,共享內存1s拉起,接口自動測試,全局鎖服務器用于獨占某些服務或操作。
ECS模式:word=system+entity; system=sys1+sys2+sysn; entity=componentN;
posted @ 2020-01-16 16:32 長戟十三千 閱讀(7) | 評論 (0)編輯 收藏
     摘要: inline是C++關鍵字,在函數聲明或定義中,函數返回類型前加上關鍵字inline,即可以把函數指定為內聯函數。這樣可以解決一些頻繁調用的函數大量消耗棧空間(棧內存)的問題。關鍵字inline必須與函數定義放在一起才能使函數成為內聯函數,僅僅將inline放在函數聲明前面不起任何作用。inline是一種“用于實現”的關鍵字,而不是一種“用于聲明”的...  閱讀全文
posted @ 2020-01-13 11:28 長戟十三千 閱讀(2) | 評論 (0)編輯 收藏
     摘要: 3)下面的函數被用來計算某個整數的平方,它能實現預期設計目標嗎?如果不能,試回答存在什么問題:1234int square(volatile int *ptr){    return ((*ptr) * (*ptr));}3)這段代碼是個惡作劇。這段代碼的目的是用來返指針*ptr指向值的平方,但是,...  閱讀全文
posted @ 2020-01-13 11:22 長戟十三千 閱讀(3) | 評論 (0)編輯 收藏

前言

江苏快三开奖结果ZIJIEDUIQISHIWOMENCHUXUECYUYANJIUHUIJIECHUDAODEYIGEGAINIAN,DANSHIDAODISHENMESHIZIJIEDUIQI?DUIQIZHUNZEYOUSHISHENME?WEISHENMEYAOZIJIEDUIQINI?ZIJIEDUIQIDUIWOMENBIANCHENGYOUSHENMEQISHI?BENWENJIANGJIANDANLIYILIZIJIEDUIQIDENEIXIESHI。

什么是字節對齊

JISUANJIZHONGNEICUNDAXIAODEJIBENDANWEISHIZIJIE(byte),LILUNSHANGLAIJIANG,KEYICONGRENYIDIZHIFANGWENMOUZHONGJIBENSHUJULEIXING,DANSHISHIJISHANG,JISUANJIBINGFEIZHUZIJIEDAXIAODUXIENEICUN,ERSHIYI2,4,HUO8DE BEISHUDEZIJIEKUAILAIDUXIENEICUN,RUCIYILAIJIUHUIDUIJIBENSHUJULEIXINGDEHEFADIZHIZUOCHUYIXIEXIANZHI,JITADEDIZHIBIXUSHI2,4HUO8DEBEISHU。NEIMEJIUYAOQIUGEZHONGSHUJULEIXINGANZHAOYIDINGDEGUIZEZAIKONGJIANSHANGPAILIE,ZHEJIUSHIDUIQI。

對齊準則是什么

江苏快三开奖结果ZONGDELAISHUO,ZIJIEDUIQIYOUYIXIAZHUNZE:

  • 結構體變量的首地址能夠被其對齊字節數大小所整除
  • 結構體每個成員相對結構體首地址的偏移都是成員大小的整數倍,如不滿足,對前一個成員填充字節以滿足。
  • 結構體的總大小為結構體對齊字節數大小的整數倍,如不滿足,最后填充字節以滿足。

我們通過一個小例子來說明是如何對齊的。
考慮下面的程序

/*================================================================ *   Copyright (C) 2018  Ltd. All rights reserved. *    *   文件名稱:testByteAlign.c *   創 建 者:shouwang *   創建日期:2018年09月15日 *   描    述: * ================================================================*/ #include<stdio.h> #include<stdint.h> struct test {     int a;     char b;     int c;     short d; }; int main(int argc,char *argv) {     /*在32位和64位的機器上,size_t的大小不同*/     printf("the size of struct test is %zu\n",sizeof(struct test));     return 0; } 

BIANYICHENG32WEICHENGXUBINGYUNXING(MORENSIZIJIEZIRANDUIQI),KEYIKANDAO,JIEGOUTItest DEDAXIAOWEI16ZIJIE,ERBUSHI11ZIJIE(aZHAN4ZIJIE,bZHAN1ZIJIE,cZHAN4ZIJIE,dZHAN2ZIJIE)

#64位機器上編譯32位程序可能需要安裝一個庫 #sudo apt-get install gcc-multilib gcc -m32 -o testByteAlign testByteAlign.c #編譯程序 chmod +x testByteAlign  #賦執行權限 ./testByteAlign  #運行 the size of struct test is 16 

實際上,結構體test的成員在內存中可能是像下面這樣分布的(數值為偏移量)
未對齊時:

江苏快三开奖结果0~345~910~11abcd

DUIQISHI:

0~345~78~1112~1314~15abTIANCHONGNEIRONGcdTIANCHONGNEIRONG

從上面可以看出,c的偏移為5,不滿足對齊要求(它的偏移量應該能夠被sizeof(int)大小整除),因此在b后面填充了3個字節,使得c的偏移為8。在b后面填充后,d已經滿足對齊要求了,為什么最后還要填充字節呢?或者說,為什么需要滿足第三條準則呢?
考慮下面的聲明

struct teArray[2]; 

江苏快三开奖结果WOMENBUNANZHIDAO,teArray[0]DEdRUGUOBUTIANCHONGZIJIE,NEIMEteArray[1]DEaPIANYIWEI14,BUMANZUDUIQIYAOQIU,YINCIdHOUMIANYEXUYAOTIANCHONGZIJIE。

為什么要字節對齊

無論數據是否對齊,大多數計算機還是能夠正確工作,而且從前面可以看到,結構體test本來只需要11字節的空間,最后卻占用了16字節,很明顯浪費了空間,那么為什么還要進行字節對齊呢?最重要的考慮是提高內存系統性能
前面我們也說到,計算機每次讀寫一個字節塊,例如,假設計算機總是從內存中取8個字節,如果一個double數據的地址對齊成8的倍數,那么一個內存操作就可以讀或者寫,但是如果這個double數據的地址沒有對齊,數據就可能被放在兩個8字節塊中,那么我們可能需要執行兩次內存訪問,才能讀寫完成。顯然在這樣的情況下,是低效的。所以需要字節對齊來提高內存系統性能。
在有些處理器中,如果需要未對齊的數據,可能不能夠正確工作甚至crash,這里我們不多討論。

實際編程中的考慮

SHIJISHANG,ZIJIEDUIQIDEXIJIEDOUYOUBIANYIQILAIWANCHENG,WOMENBUXUYAOTEYIJINXINGZIJIEDEDUIQI,DANBINGBUYIWEIZHUWOMENBUXUYAOGUANZHUZIJIEDUIQIDEWENTI。

空間存儲

還是考慮前面的結構體test,其占用空間大小為16字節,但是如果我們換一種聲明方式,調整變量的順序,重新運行程序,最后發現結構體test占用大小為12字節

struct test {     int a;     char b;     short d;     int c; }; 

KONGJIANCUNCHUQINGKUANGRUXIA,bHEcCUNCHUZAILEYIGEZIJIEKUAIZHONG:

江苏快三开奖结果0~3456~78~11abTIANCHONGNEIRONGcd

YEJIUSHISHUO,RUGUOWOMENZAISHEJIJIEGOUDESHIHOU,HELIDIAOZHENGCHENGYUANDEWEIZHI,KEYIDADAJIESHENGCUNCHUKONGJIAN。

跨平臺通信

YOUYUBUTONGPINGTAIDUIQIFANGSHIKENENGBUTONG,RUCIYILAI,TONGYANGDEJIEGOUZAIBUTONGDEPINGTAIQIDAXIAOKENENGBUTONG,ZAIWUYISHIDEQINGKUANGXIA,HUXIANGFASONGDESHUJUKENENGCHUXIANCUOLUAN,SHENZHIYINFAYANZHONGDEWENTI。YINCI,WEILEBUTONGCHULIQIZHIJIANNENGGOUZHENGQUEDECHULIXIAOXI,WOMENYOULIANGZHONGKEXUANDECHULIFANGFA。

  • 1字節對齊
  • 自己對結構進行字節填充

我們可以使用偽指令#pragma pack(n)(n為字節對齊數)來使得結構間一字節對齊。
同樣是前面的程序,如果在結構體test的前面加上偽指令,即如下:

#pragma pack(1) /*1字節對齊*/ struct test {     int a;     char b;     int c;     short d; }; #pragma pack()/*還原默認對齊*/ 

ZAIZHEYANGDESHENGMINGXIA,RENHEPINGTAIJIEGOUTItestDEDAXIAODOUWEI11ZIJIE,ZHEYANGZUONENGGOUBAOZHENGKUAPINGTAIDEJIEGOUDAXIAOYIZHI,TONGSHIHUANJIESHENGLEKONGJIAN,DANBUXINGDESHI,JIANGDILEXIAOLV。

DANGRANLEDUIYUDANGEJIEGOUTI,gccHUANYOURUXIADEFANGFA,SHIQI1ZIJIEDUIQI

struct test {     int a;     char b;     int c;     short d; }__attribute__ ((packed)); 

ZHU:

  • __attribute__((aligned (n))),讓所作用的結構成員對齊在n字節自然邊界上。如果結構中有成員的長度大于n,則按照最大成員的長度來對齊。
  • __attribute__ ((packed)),取消結構在編譯過程中的優化對齊,也可以認為是1字節對齊。

CHULEQIANMIANDE1ZIJIEDUIQI,HUANKEYIJINXINGRENWEIDETIANCHONG,JItestJIEGOUTISHENGMINGRUXIA:

struct test {     int a;     char b;     char reserve[3];     int c;     short d;     char reserve1[2]; }; 

江苏快三开奖结果FANGWENXIAOLVGAO,DANBINGBUJIESHENGKONGJIAN,TONGSHIKUOZHANXINGBUSHIHENHAO,LIRU,DANGZIJIEDUIQIYOUBIANHUASHI,XUYAOTIANCHONGDEZIJIESHUKENENGJIUHUIFASHENGBIANHUA。

總結

江苏快三开奖结果SUIRANWOMENBUXUYAOJUTIGUANXINZIJIEDUIQIDEXIJIE,DANSHIRUGUOBUGUANZHUZIJIEDUIQIDEWENTI,KENENGHUIZAIBIANCHENGZHONGYUDAONANYILIJIEHUOJIEJUEDEWENTI。YINCIZHENDUIZIJIEDUIQI,ZONGJIELEYIXIACHULIJIANYI:

  • 結構體成員合理安排位置,以節省空間
  • 跨平臺數據結構可考慮1字節對齊,節省空間但影響訪問效率
  • 跨平臺數據結構人為進行字節填充,提高訪問效率但不節省空間
  • 本地數據采用默認對齊,以提高訪問效率
posted @ 2020-01-09 16:54 長戟十三千 閱讀(3) | 評論 (0)編輯 收藏
Linux 的虛擬內存管理有幾個關鍵概念: 
1、每個進程都有獨立的虛擬地址空間,進程訪問的虛擬地址并不是真正的物理地址; 
2、虛擬地址可通過每個進程上的頁表(在每個進程的內核虛擬地址空間)與物理地址進行映射,獲得真正物理地址; 
3、如果虛擬地址對應物理地址不在物理內存中,則產生缺頁中斷,真正分配物理地址,同時更新進程的頁表;如果此時物理內存已耗盡,則根據內存替換算法淘汰部分頁面至物理磁盤中。 
   
基于以上認識,進行了如下分析:
一、Linux 虛擬地址空間如何分布?
Linux 使用虛擬地址空間,大大增加了進程的尋址空間,由低地址到高地址分別為: 
1、只讀段:該部分空間只能讀,不可寫;(包括:代碼段、rodata 段(C常量字符串和#define定義的常量) )
2、數據段:保存全局變量、靜態變量的空間; 
3、堆 :就是平時所說的動態內存, malloc/new 大部分都來源于此。其中堆頂的位置可通過函數 brk 和 sbrk 進行動態調整。 
4、文件映射區域 :如動態庫、共享內存等映射物理空間的內存,一般是 mmap 函數所分配的虛擬地址空間。 
5、棧:用于維護函數調用的上下文空間,一般為 8M ,可通過 ulimit –s 查看。 
6、內核虛擬空間:用戶代碼不可見的內存區域,由內核管理(頁表就存放在內核虛擬空間)。
下圖是 32 位系統典型的虛擬地址空間分布(來自《深入理解計算機系統》)。
32 位系統有4G 的地址空間::
      其中 0x08048000~0xbfffffff 是用戶空間,0xc0000000~0xffffffff 是內核空間,包括內核代碼和數據、與進程相關的數據結構(如頁表、內核棧)等。另外,%esp 執行棧頂,往低地址方向變化;brk/sbrk 函數控制堆頂_edata往高地址方向變化。
64位系統結果怎樣呢? 64 位系統是否擁有 2^64 的地址空間嗎? 
事實上, 64 位系統的虛擬地址空間劃分發生了改變: 
1、地址空間大小不是2^32,也不是2^64,而一般是2^48。因為并不需要 2^64 這么大的尋址空間,過大空間只會導致資源的浪費。64位Linux一般使用48位來表示虛擬地址空間,40位表示物理地址,
這可通過 /proc/cpuinfo 來查看 
address sizes   : 40 bits physical, 48 bits virtual 
2、其中,0x0000000000000000~0x00007fffffffffff 表示用戶空間, 0xFFFF800000000000~ 0xFFFFFFFFFFFFFFFF 表示內核空間,共提供 256TB(2^48) 的尋址空間。
這兩個區間的特點是,第 47 位與 48~63 位相同,若這些位為 0 表示用戶空間,否則表示內核空間。 
3、用戶空間由低地址到高地址仍然是只讀段、數據段、堆、文件映射區域和棧;
 
二、malloc和free是如何分配和釋放內存?
如何查看進程發生缺頁中斷的次數?
         用ps -o majflt,minflt -C program命令查看。
          majflt代表major fault,中文名叫大錯誤,minflt代表minor fault,中文名叫小錯誤。
          這兩個數值表示一個進程自啟動以來所發生的缺頁中斷的次數。
發成缺頁中斷后,執行了那些操作?
當一個進程發生缺頁中斷的時候,進程會陷入內核態,執行以下操作: 
1、檢查要訪問的虛擬地址是否合法 
2、查找/分配一個物理頁 
3、填充物理頁內容(讀取磁盤,或者直接置0,或者啥也不干) 
4、建立映射關系(虛擬地址到物理地址) 
重新執行發生缺頁中斷的那條指令 
如果第3步,需要讀取磁盤,那么這次缺頁中斷就是majflt,否則就是minflt。 
內存分配的原理
從操作系統角度來看,進程分配內存有兩種方式,分別由兩個系統調用完成:brk和mmap(不考慮共享內存)。
1、brk是將數據段(.data)的最高地址指針_edata往高地址推;
2、mmap是在進程的虛擬地址空間中(堆和棧中間,稱為文件映射區域的地方)找一塊空閑的虛擬內存。
     這兩種方式分配的都是虛擬內存,沒有分配物理內存。在第一次訪問已分配的虛擬地址空間的時候,發生缺頁中斷,操作系統負責分配物理內存,然后建立虛擬內存和物理內存之間的映射關系。
在標準C庫中,提供了malloc/free函數分配釋放內存,這兩個函數底層是由brk,mmap,munmap這些系統調用實現的。
下面以一個例子來說明內存分配的原理:
情況一、malloc小于128k的內存,使用brk分配內存,將_edata往高地址推(只分配虛擬空間,不對應物理內存(因此沒有初始化),第一次讀/寫數據時,引起內核缺頁中斷,內核才分配對應的物理內存,然后虛擬地址空間建立映射關系),如下圖:
1、進程啟動的時候,其(虛擬)內存空間的初始布局如圖1所示。
      其中,mmap內存映射文件是在堆和棧的中間(例如libc-2.2.93.so,其它數據文件等),為了簡單起見,省略了內存映射文件。
      _edata指針(glibc里面定義)指向數據段的最高地址。 
2、進程調用A=malloc(30K)以后,內存空間如圖2:
      malloc函數會調用brk系統調用,將_edata指針往高地址推30K,就完成虛擬內存分配。
      你可能會問:只要把_edata+30K就完成內存分配了?
      事實是這樣的,_edata+30K只是完成虛擬地址的分配,A這塊內存現在還是沒有物理頁與之對應的,等到進程第一次讀寫A這塊內存的時候,發生缺頁中斷,這個時候,內核才分配A這塊內存對應的物理頁。也就是說,如果用malloc分配了A這塊內容,然后從來不訪問它,那么,A對應的物理頁是不會被分配的。 
3、進程調用B=malloc(40K)以后,內存空間如圖3。
情況二、malloc大于128k的內存,使用mmap分配內存,在堆和棧之間找一塊空閑內存分配(對應獨立內存,而且初始化為0),如下圖:
4、進程調用C=malloc(200K)以后,內存空間如圖4:
      默認情況下,malloc函數分配內存,如果請求內存大于128K(可由M_MMAP_THRESHOLD選項調節),那就不是去推_edata指針了,而是利用mmap系統調用,從堆和棧的中間分配一塊虛擬內存。
      這樣子做主要是因為::
      brk分配的內存需要等到高地址內存釋放以后才能釋放(例如,在B釋放之前,A是不可能釋放的,這就是內存碎片產生的原因,什么時候緊縮看下面),而mmap分配的內存可以單獨釋放。
      當然,還有其它的好處,也有壞處,再具體下去,有興趣的同學可以去看glibc里面malloc的代碼了。 
5、進程調用D=malloc(100K)以后,內存空間如圖5;
6、進程調用free(C)以后,C對應的虛擬內存和物理內存一起釋放。
7、進程調用free(B)以后,如圖7所示:
        B對應的虛擬內存和物理內存都沒有釋放,因為只有一個_edata指針,如果往回推,那么D這塊內存怎么辦呢?
當然,B這塊內存,是可以重用的,如果這個時候再來一個40K的請求,那么malloc很可能就把B這塊內存返回回去了。 
8、進程調用free(D)以后,如圖8所示:
        B和D連接起來,變成一塊140K的空閑內存。
9、默認情況下:
       當最高地址空間的空閑內存超過128K(可由M_TRIM_THRESHOLD選項調節)時,執行內存緊縮操作(trim)。在上一個步驟free的時候,發現最高地址空閑內存超過128K,于是內存緊縮,變成圖9所示。
三、既然堆內內存brk和sbrk不能直接釋放,為什么不全部使用 mmap 來分配,munmap直接釋放呢? 
        既然堆內碎片不能直接釋放,導致疑似“內存泄露”問題,為什么 malloc 不全部使用 mmap 來實現呢(mmap分配的內存可以會通過 munmap 進行 free ,實現真正釋放)?而是僅僅對于大于 128k 的大塊內存才使用 mmap ? 
        其實,進程向 OS 申請和釋放地址空間的接口 sbrk/mmap/munmap 都是系統調用,頻繁調用系統調用都比較消耗系統資源的。并且, mmap 申請的內存被 munmap 后,重新申請會產生更多的缺頁中斷。例如使用 mmap 分配 1M 空間,第一次調用產生了大量缺頁中斷 (1M/4K 次 ) ,當munmap 后再次分配 1M 空間,會再次產生大量缺頁中斷。缺頁中斷是內核行為,會導致內核態CPU消耗較大。另外,如果使用 mmap 分配小內存,會導致地址空間的分片更多,內核的管理負擔更大。
        同時堆是一個連續空間,并且堆內碎片由于沒有歸還 OS ,如果可重用碎片,再次訪問該內存很可能不需產生任何系統調用和缺頁中斷,這將大大降低 CPU 的消耗。 因此, glibc 的 malloc 實現中,充分考慮了 sbrk 和 mmap 行為上的差異及優缺點,默認分配大塊內存 (128k) 才使用 mmap 獲得地址空間,也可通過 mallopt(M_MMAP_THRESHOLD, <SIZE>) 來修改這個臨界值。
 
四、如何查看進程的缺頁中斷信息? 
可通過以下命令查看缺頁中斷信息 
ps -o majflt,minflt -C <program_name> 
ps -o majflt,minflt -p <pid> 
其中:: majflt 代表 major fault ,指大錯誤;
           minflt 代表 minor fault ,指小錯誤。
這兩個數值表示一個進程自啟動以來所發生的缺頁中斷的次數。
其中 majflt 與 minflt 的不同是::
        majflt 表示需要讀寫磁盤,可能是內存對應頁面在磁盤中需要load 到物理內存中,也可能是此時物理內存不足,需要淘汰部分物理頁面至磁盤中。
五、C語言的內存分配方式與malloc
  
C語言跟內存分配方式
(1) 從靜態存儲區域分配。內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在。例如全局變量,static變量。
(2) 在棧上創建。在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分配運
算內置于處理器的指令集中,效率很高,但是分配的內存容量有限。
(3)從堆上分配,亦稱動態內存分配。程序在運行的時候用malloc或new申請任意多少的內存,程序員自己負責在何時用free或delete釋放內存。動態內存的生存期由我們決定,使用非常靈活,但問題也最多
     
      C語言跟內存申請相關的函數主要有 alloc,calloc,malloc,free,realloc,sbrk等.其中alloc是向棧申請內存,因此無需釋放. malloc分配的內存是位于堆中的,并且沒有初始化內存的內容,因此基本上malloc之后,調用函數memset來初始化這部分的內存空間.calloc則將初始化這部分的內存,設置為0. 而realloc則對malloc申請的內存進行大小的調整.申請的內存最終需要通過函數free來釋放. 而sbrk則是增加數據段的大小;
       malloc/calloc/free基本上都是C函數庫實現的,跟OS無關.C函數庫內部通過一定的結構來保存當前有多少可用內存.如果程序 malloc的大小超出了庫里所留存的空間,那么將首先調用brk系統調用來增加可用空間,然后再分配空間.free時,釋放的內存并不立即返回給os, 而是保留在內部結構中. 可以打個比方: brk類似于批發,一次性的向OS申請大的內存,而malloc等函數則類似于零售,滿足程序運行時的要求.這套機制類似于緩沖.
使用這套機制的原因: 系統調用不能支持任意大小的內存分配(有的系統調用只支持固定大小以及其倍數的內存申請,這樣的話,對于小內存的分配會造成浪費; 系統調用申請內存代價昂貴,涉及到用戶態和核心態的轉換.
函數malloc()和calloc()都可以用來分配動態內存空間,但兩者稍有區別。
      在Linux系統上,程序被載入內存時,內核為用戶進程地址空間建立了代碼段、數據段和堆棧段,在數據段與堆棧段之間的空閑區域用于動態內存分配。
      內核數據結構mm_struct中的成員變量start_code和end_code是進程代碼段的起始和終止地址,start_data和 end_data是進程數據段的起始和終止地址,start_stack是進程堆棧段起始地址,start_brk是進程動態內存分配起始地址(堆的起始 地址),還有一個 brk(堆的當前最后地址),就是動態內存分配當前的終止地址。
C語言的動態內存分配基本函數是malloc(),在Linux上的基本實現是通過內核的brk系統調用。brk()是一個非常簡單的系統調用,只是簡單地改變mm_struct結構的成員變量brk的值。
      mmap系統調用實現了更有用的動態內存分配功能,可以將一個磁盤文件的全部或部分內容映射到用戶空間中,進程讀寫文件的操作變成了讀寫內存的操作。在 linux/mm/mmap.c文件的do_mmap_pgoff()函數,是mmap系統調用實現的核心。do_mmap_pgoff()的代碼,只是新建了一個vm_area_struct結構,并把file結構的參數賦值給其成員變量m_file,并沒有把文件內容實際裝入內存。
Linux內存管理的基本思想之一,是只有在真正訪問一個地址的時候才建立這個地址的物理映射。
————————————————
版權聲明:本文為CSDN博主「gfgdsg」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:http://blog.csdn.net/gfgdsg/article/details/42709943
posted @ 2019-12-25 15:36 長戟十三千 閱讀(3) | 評論 (0)編輯 收藏
     摘要: brk() , sbrk() 的聲明如下:#include <unistd.h>int brk(void *addr);void *sbrk(intptr_t increment);這兩個函數都用來改變 "program break" (程序間斷點)的位置,這個位置可參考下圖:如 man 里說的:引用brk()  and  sbrk() chan...  閱讀全文
posted @ 2019-12-25 15:25 長戟十三千 閱讀(4) | 評論 (0)編輯 收藏

ZAIwindowsPINGTAI,YOUYIGEJIANDANDEFANGFALAIZHUIZONGDIAOYONGHANSHUDEDUIZHAN,JIUSHILIYONGHANSHUCaptureStackBackTrace,DANSHIZHEGEHANSHUBUNENGDEDAOJUTIDIAOYONGHANSHUDEMINGCHENG,ZHINENGDEDAODIZHI,DANGRANWOMENKEYITONGGUOFANHUIBIANDEFANGSHITONGGUODIZHIDEDAOHANSHUDEMINGCHENG,YIJIJUTIDIAOYONGDEFANHUIBIANDAIMA,DANSHIDUIYUYOUDESHIHOUWOMENXUYAOZHIJIEDEDAOHANSHUDEMINGCHENG,ZHEGESHIHOUJUBUNENGSHIYONGZHEGEFANGFA,DUIYUZHEZHONGXUQIUWOMENKEYISHIYONGHANSHU:SymInitialize、StackWalk、SymGetSymFromAddr、SymGetLineFromAddr、SymCleanup。

原理

JIBENSHANGSUOYOUGAOJIYUYANDOUYOUZHUANMENWEIHANSHUZHUNBEIDEDUIZHAN,YONGLAICUNCHUHANSHUZHONGDINGYIDEBIANLIANG,ZAIC/C++ZHONGZAIDIAOYONGHANSHUZHIQIANHUIBAOCUNDANGQIANHANSHUDEXIANGGUANHUANJING,ZAIDIAOYONGHANSHUSHISHOUXIANJINXINGCANSHUYAZHAN,RANHOUcallZHILINGJIANGDANGQIANeipDEZHIYARUDUIZHANZHONG,RANHOUDIAOYONGHANSHU,HANSHUSHOUXIANHUIJIANGZISHENDUIZHANDEZHANDIDIZHIBAOCUNZAIebpZHONG,RANHOUTAIGAOespBINGCHUSHIHUABENSHENDEDUIZHAN,TONGGUODUOCIDIAOYONGZUIZHONGZAIDUIZHANDUANXINGCHENGZHEYANGDEBUJU

ZHELIDUIHANSHUDEYUANLIZUOJIANDANDEJIESHAO,YOUXINGQUDEKEYIKANWODELINGYIPIANGUANYUCHANSHUYUANLIJIANGJIEDEBOKE, VC++BIANYIQIZAIBIANYISHIDUIHANSHUMINGCHENGYUDIZHIDOUYOUXIANGXIDEJILU,BIANYICHULAIDECHENGXUDOUYOUYIGEFUHAOCHANGLIANGBIAO,JIANGFUHAOCHANGLIANGYUTADUIYINGDEDIZHIXINGCHENGYINGSHE,ZAISOUSUOSHISHOUXIANGENJUZHEXIEDUIZHANHUANJINGZHAODAODUIYINGDIZHI,RANHOUGENJUDIZHIZAIFUHAOCHANGLIANGBIAOZHONG,ZHAODAOJUTIDIAOYONGDEXINXI,ZHESHIYIGEHENFUZADEGONGCHENG,XUYAODUIBIANYIYUANLIHEHUIBIANYOUHENQIANGDEJICHU,XINGYUNDESHI,RUJINZHEXIEGONGZUOBUXUYAOCHENGXUYUANZIJIQUZUO,windowsBANGZHUWOMENFENPEILEYIZUAPI,ZAIBIANXIECHENGXUSHIZHIXUYAODIAOYONGAPIJIKE

函數說明

SymInitialize:ZHEGEHANSHUZHUYAOYONGZUOCHUSHIHUAXIANGGUANHUANJING。 SymCleanup:QINGCHUZHEGECHUSHIHUADEXIANGGUANHUANJING,ZAIDIAOYONGSymInitializeZHIHOUXUYAODIAOYONGSymCleanup,JINXINGSHIFANGZIYUANDECAOZUO StackWalk:CHENGXUDEGONGNENGZHUYAOYOUZHEGEHANSHUSHIXIAN,HANSHUHUICONGCHUSHIHUASHIDEDUIZHANDINGKAISHIXIANGXIACHAZHAOXIAYIGEDUIZHANDEXINXI,YUANXINGRUXIA:

BOOL WINAPI StackWalk(   __in          DWORD MachineType, //機器類型現在一般是intel的x86系列,這個時候填入IMAGE_FILE_MACHINE_I386   __in          HANDLE hProcess, //追蹤的進程句柄   __in          HANDLE hThread, //追蹤的線程句柄   __in_out      LPSTACKFRAME StackFrame, //記錄的追蹤到的堆棧信息   __in_out      PVOID ContextRecord, //記錄當前的線程環境   __in          PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,   __in          PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,   __in          PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,   __in          PTRANSLATE_ADDRESS_ROUTINE TranslateAddress //后面的四個參數都是回掉函數,有系統自行調用,而且這些函數都是定義好的,只需要填入相應的函數名稱 );

江苏快三开奖结果XUYAOZHUYIDEYIDIANSHI,ZAISHOUCIDIAOYONGGAIHANSHUSHIXUYAODUIStackFrameZHONGDEAddrPC、AddrFrame、AddrStackZHESANGECHENGYUANJINXINGCHUSHIHUA,TIANRUXIANGGUANZHI,YIBIANHANSHUCONGCICHUXIANCHENGDUIZHANDEZHANDINGJINXINGSOUSUO,FOUZEDIAOYONGHANSHUJIANGSHIBAI,JUTIRUHETIANXIEQINGKANMSDN。

SymGetSymFromAddr:根據獲取到的函數地址得到函數名稱、堆棧大小等信息,這個函數的原型如下: BOOL WINAPI SymGetSymFromAddr(   __in          HANDLE hProcess, //進程句柄   __in          DWORD Address, //函數地址   __out         PDWORD Displacement, //返回該符號常量的位移或者填入NULL,不獲取此值   __out         PIMAGEHLP_SYMBOL Symbol//返回堆棧信息 );

SymGetLineFromAddr:GENJUDEDAODEDIZHIZHI,HUOQUDIAOYONGHANSHUDEXIANGGUANXINXI。ZHUYAOJILUSHIZAINAGEWENJIAN,NAXINGDIAOYONGLEGAIHANSHU,XIAMIANSHIHANSHUYUANXING:

BOOL WINAPI SymGetLineFromAddr(   __in          HANDLE hProcess,   __in          DWORD dwAddr,   __out         PDWORD pdwDisplacement,   __out         PIMAGEHLP_LINE Line );

江苏快三开奖结果TACANSHUDEHANYIYUSymGetSymFromAddr,XIANGTONG。 TONGGUOSHANGMIANDUIHANSHUDESHUOMING,WOMENKEYIZHIDAO,WEILEZHUIZONGHANSHUDIAOYONGDEXIANGXIXINXI,DAZHIBUZOURUXIA: 1. SHOUXIANDIAOYONGHANSHUSymInitializeJINXINGXIANGGUANDECHUSHIHUAGONGZUO。 2. TIANCHONGJIEGOUTIStackFrameDEXIANGGUANXINXI,QUEDINGCONGHECHUKAISHIZHUIZONG。 3. XUNHUANDIAOYONGStackWalkHANSHU,CONGZHIDINGWEIZHI,XIANGXIAYIZHIZHUIZONGDAOZUIHOU。 4. MEICIJIANGHUOQUDEDIZHIFENBIECHUANRUSymGetSymFromAddr、SymGetLineFromAddr,DEDAOHANSHUDEXIANGXIXINXI 5. DIAOYONGSymCleanup,JIESHUZHUIZONG DANSHIXUYAOZHUYIDEYIDIANSHI,HANSHUStackWalkHUISHUNZHUXIANCHENGDUIZHANJINXINGCHAZHAO,RUGUOZAIDIAOYONGZHIQIAN,MOUGEHANSHUYIJINGFANHUILE,TADEDUIZHANBEIHUISHOU,NEIMEHANSHUStackWalkZIRANBUHUIZHUIZONGDAOGAIHANSHUDEDIAOYONG。

具體實現

void InitTrack() {     g_hHandle = GetCurrentProcess();      SymInitialize(g_hHandle, NULL, TRUE); }  void StackTrack() {     g_hThread = GetCurrentThread();     STACKFRAME sf = { 0 };      sf.AddrPC.Offset = g_context.Eip;     sf.AddrPC.Mode = AddrModeFlat;      sf.AddrFrame.Offset = g_context.Ebp;     sf.AddrFrame.Mode = AddrModeFlat;      sf.AddrStack.Offset = g_context.Esp;     sf.AddrStack.Mode = AddrModeFlat;      typedef struct tag_SYMBOL_INFO     {         IMAGEHLP_SYMBOL symInfo;         TCHAR szBuffer[MAX_PATH];     } SYMBOL_INFO, *LPSYMBOL_INFO;      DWORD dwDisplament = 0;     SYMBOL_INFO stack_info = { 0 };     PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)&stack_info;     pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);     pSym->MaxNameLength = sizeof(SYMBOL_INFO) - offsetof(SYMBOL_INFO, symInfo.Name);     IMAGEHLP_LINE ImageLine = { 0 };     ImageLine.SizeOfStruct = sizeof(IMAGEHLP_LINE);      while (StackWalk(IMAGE_FILE_MACHINE_I386, g_hHandle, g_hThread, &sf, &g_context, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL))     {         SymGetSymFromAddr(g_hHandle, sf.AddrPC.Offset, &dwDisplament, pSym);         SymGetLineFromAddr(g_hHandle, sf.AddrPC.Offset, &dwDisplament, &ImageLine);         printf("當前調用函數 : %08x+%s(FILE[%s]LINE[%d])\n", pSym->Address, pSym->Name, ImageLine.FileName, ImageLine.LineNumber);     }  }  void UninitTrack() {     SymCleanup(g_hHandle); }

CESHICHENGXURUXIA:

void func1() {     OPEN_STACK_TRACK; }  void func2() {     func1(); }  void func3() {     func2();  } void func4() {     printf("hello\n"); }  int _tmain(int argc, TCHAR* argv[]) {     func4();     func3();     func3();     return 0; }

江苏快三开奖结果OPEN_STACK_TRACKSHIYIGEHONG,TADEDINGYIRUXIA:

#define OPEN_STACK_TRACK\  HANDLE hThread = GetCurrentThread();\ GetThreadContext(hThread, &g_context);\ __asm{call $ + 5}\ __asm{pop eax}\ __asm{mov g_context.Eip, eax}\ __asm{mov g_context.Ebp, ebp}\ __asm{mov g_context.Esp, esp}\ InitTrack();\ StackTrack();\ UninitTrack();

ZHEGECHENGXUXUYAOZHUYIYIXIAJIDIAN: 1. RUGUOXIANGYAOZHUIZONGSUOYOUDIAOYONGDEHANSHU,XUYAOJIANGZHEGEHONGFANGZHIDAOZUIHOUDIAOYONGDEWEIZHI,DANGRANQIANTISHICISHIZHIQIANBEIDIAOHANSHUDEDUIZHANRENGRANCUNZAI。DANGRANKEYIZAIDIAOYONGQIANJIANDANDEJISUAN,ZHAOCHUZAINAGEWEIZHISHISUOYOUHANSHUDOUMEIYOUDIAOYONGWANCHENGDE,BUGUOZHEYANGKENENGJIUYUCHENGXUDECHUZHONGXIANGBEI,BIJINGCHENGXUBENSHENJIUSHIWEILEHUOQUDUIZHANDEDIAOYONGXINXI。。。。 2. IMAGEHLP_SYMBOLDEJIEGOUTIZHONGGUANYUNameDECHENGYUAN,ZHIYOUYIGEZIJIE,ERHANSHUSymGetSymFromAddrZAITIANRUZHISHISHIMEIYOUGUANXINZHEGESHIJIDAXIAO,TAZHISHIJIANDANDETIANCHONG,ZHEJIUZAOCHENGLEHUANCHONGQUYICHUDEQINGKUANG,WEILEBIMIANWOMENXUYAOZAINameHOUMIANEWAIGEIYIDINGDAXIAODEHUANCHONGQU,YONGLAIJIESHOUSHUJU,ZHEYEJIUSHIWOMENDINGYIZHEGEJIEGOUTISYMBOL_INFODEYUANYIN。LINGWAIIMAGEHLP_SYMBOLZHONGDEMaxNameLengthCHENGYUANSHIZHINameDEZUIDACHANGDU,XUYAOGENJUGEIDINGDEHUANCHONGQU,JINXINGJISUAN。 3. CONGCESHICHENGXULAIKAN,ZAIJINXINGZHUIZONGSHIfunc4YIJINGDIAOYONGWANCHENG,ERWOMENZAIHUOQUXIANCHENGDEYUNXINGSHIHUANJINGg_contextSHIHANSHUGetThreadContext,YEZAIDUIZHANZHONG,ZUIZHONGDEDAODEJIEGUOZHONGBIRANBAOHANGetThreadContextDEDIAOYONGXINXI,RUGUOXIANGQUDIAOZHEGEXINXI,ZHIXUYAOXIUGAIHUODEXINXIDEZHI,JIRANHANSHUStackWalkSHIGENJUDUIZHANJINXINGZHUIZONG,NEIMEZHIXUYAOXIUGAIDUIYINGDUIZHANDEXINXIJIKE,XUYAOXIUGAIeip 、ebp、espDEZHI,GUANYUesp ebpDEZHIHENHAOXIUGAI,KEYIZAIDUIYINGHANSHUZHONGesp ebpZHEXIEJICUNQIDEZHI,EReipDEZHIJIUBUNEIMEHAOHUOQU,BENSHENGLIYONGmovZHILINGDEDAOeipDEZHITAYESHIZHILING,HUIGAIBIANeipDEZHI,CONGERZAOCHENGHUOQUDAODEeipDEZHIBUZHUNQUE,SUOYIWOMENLIYONGcallZHILING,XIANBAOCUNDANGQIANeipDEZHIDAODUIZHAN,RANHOUZAICONGDUIZHANZHONGQUCHU。callZHILINGDESHIZHISHI push eipHEjmp addrZHILINGDEZUHE,BINGBUYIDINGFEIYAODIAOYONGHANSHU。callZHILINGDEDAXIAOWEI5GEZIJIE,SUOYIcall $ + 5BIAOSHIXIANBAOCUNeipZAITIAOZHUANDAOTADEXIAYITIAOZHILINGCHU。ZHEYANGJIUKEYIYOUXIAODEBIMIANJIANCEDAOGetThreadContextZHONGDEXIANGGUANHANSHUDIAOYONG

posted @ 2019-12-19 12:39 長戟十三千 閱讀(3) | 評論 (0)編輯 收藏
     摘要: 文檔名稱:Windows NT Stack Trace文檔維護:welfear創建時間:2009年6月7日更新內容:對StackWalk的分析(2009.6.17)更新內容:對x64棧的分析(2009.6.19) 在系統軟件開發中有時會有得到函數調用者的信息的需要,為此WindowsNT專門提供了調用RtlGetCallerAddress為內核開發者使用,但它并沒有公開所以也就不能為驅動...  閱讀全文
posted @ 2019-12-19 12:34 長戟十三千 閱讀(6) | 評論 (0)編輯 收藏

targetServer = serverList[hash(key) % serverList.size]

江苏快三开奖结果ZHIJIEYONGkeyDEhashZHI(JISUANkeyDEhashZHIDEFANGFAKEYIZIYOUXUANZE,BIRUSUANFACRC32、MD5,SHENZHIBENDIhashXITONG,RUDEhashcode)MOSHANGserverZONGSHULAIDINGWEIMUBIAOserver。ZHEZHONGSUANFABUJINJIANDAN,ERQIEJUYOUBUCUODESUIJIFENBUTEXING。

江苏快三开奖结果DANSHIWENTIYEHENMINGXIAN,serverZONGSHUBUNENGQINGYIBIANHUA。YINWEIRUGUOZENGJIA/JIANSHAOmemcached serverDESHULIANG,DUIYUANXIANCUNCHUDESUOYOUkeyDEHOUXUCHAXUNDOUJIANGDINGWEIDAOBIEDEserverSHANG,DAOZHISUOYOUDEcacheDOUBUNENGBEIMINGZHONGERSHIXIAO。

(consistent hash)
相對于取模的算法,一致性hash算法除了計算key的hash值外,還會計算每個server對應的hash值,然后將這些hash值映射到一個有限的值域上(比如0~2^32)。通過尋找hash值大于hash(key)的最小server作為存儲該key數據的目標server。如果找不到,則直接把具有最小hash值的server作為目標server。

為了方便理解,可以把這個有限值域理解成一個環,值順時針遞增。

如上圖所示,集群中一共有5個memcached server,已通過server的hash值分布到環中。

如果現在有一個寫入cache的請求,首先計算x=hash(key),映射到環中,然后從x順時針查找,把找到的第一個server作為目標server來存儲cache,如果超過了2^32仍然找不到,則命中第一個server。比如x的值介于A~B之間,那么命中的server節點應該是B節點

江苏快三开奖结果可以看到,通過這種算法,對于同一個key,存儲和后續的查詢都會定位到同一個memcached server上。

那么它是怎么解決增/刪server導致的cache不能命中的問題呢?
假設,現在增加一個server F,如下圖


此時,cache不能命中的問題仍然存在,但是只存在于B~F之間的位置(由C變成了F),其他位置(包括F~C)的cache的命中不受影響(刪除server的情況類似)。盡管仍然有cache不能命中的存在,但是相對于取模的方式已經大幅減少了不能命中的cache數量。

虛擬節點
但是,這種算法相對于取模方式也有一個缺陷:當server數量很少時,很可能他們在環中的分布不是特別均勻,進而導致cache不能均勻分布到所有的server上。

posted @ 2019-12-18 15:42 長戟十三千 閱讀(11) | 評論 (0)編輯 收藏