log4j2之所以能在異步寫日誌時性能提高這麼多,離不開優秀的mq組件Disruptor。
目前使用該隊列的知名軟件包括但不限於Apache Storm、Camel、Log4j2。
底層隊列的實現對性能的影響是最大的。logback使用的是異步appender,log4j2使用的是disruptor。
異步Appender的實現,內部內置了一個BlockingQueue隊列,具體實現採用了ArrayBlockingQueue。而Disruptor則是使用了Ringbuffer。
性能上的優劣,絕大部分原因都是數據模型的問題,往下我們分析一下BlockingQueue和disruptor的實現方式:
1、ArrayBlockingQueue
ArrayBlockingQueue採用的是加鎖的方式來處理線程安全問題的。
加鎖的問題,雖然歷代JDK一直投入大量的精力去解決問題,比如優化Sync關鍵字的實現方式、添加讀寫鎖等,但是由於結構特性的問題,一直無法從根本上解決性能開銷問題。
2、Disputor
Disputor採用了環形數據結構Ringbuffer來解決這個問題(他們稱之爲魔法圓環,或魔法圓圈之類的),此種數據結構的有點是,不需要記錄額外的下標,直接由JNI返回可以操作的地址,然後當多線程併發讀寫的時候,使用的也是無鎖化cas方式。
這樣,不能使用1級緩存和加鎖操作的問題就解決了(關於CAS大家可自行谷歌,有非常多的文章來介紹)。