問題還有答案都在,歡迎大家一起討論指正澎蛛。
如何實現(xiàn)動態(tài)修改配置
我提到 1)通過MBean來保存配置信息啡彬,JMX來修改配置压真;還提到log4j2就是通過這種機制來實現(xiàn)日志級別的動態(tài)修改杆煞;2)開放telnet接口或者h(yuǎn)ttp接口來允許參數(shù)的修改;
他提到如何實現(xiàn)中心配置腐泻,我提到了zookeeper决乎,而且提到一個好處,當(dāng)參數(shù)修改時派桩,可以實時通知构诚;他提到zookeeper的客戶端需要保持長連接才能接收參數(shù)變化的通知,這樣連接數(shù)會很多铆惑,有沒有其他方式范嘱;我提到可以通過push的方式送膳,短連接來發(fā)送通知的方式。
Vertx的線程模式
線程模型和Netty的區(qū)別丑蛤,回答不上來叠聋,只說了下Vertx的線程模型 - 分發(fā)線程和工作線程
Vertx和RxJava的區(qū)別
都是響應(yīng)式框架,區(qū)別是什么受裹?回答不上來
用了什么validation框架
Vertx-contract碌补,若干個內(nèi)置的validation rule,實質(zhì)是對應(yīng)一個正則表達(dá)棉饶;可以自定義validation rule厦章,例如某個API的枚舉類型數(shù)據(jù);
NIO的BIO的區(qū)別
我回答到NIO內(nèi)有selector照藻,它可以注冊事件袜啃,從而提高線程的使用效率;他問到selector背后的實現(xiàn)幸缕,我提到了epoll群发;繼續(xù)問我是否知道epoll的兩種觸發(fā)方式 - 水平觸發(fā)和邊緣觸發(fā),我回答不上來冀值。
Redis分布式鎖的實現(xiàn)
我回答使用redisson的Redloc算法實現(xiàn)分布式鎖也物,它提到了這個算法還是會有問題,但想不起來什么場景下會有問題了列疗。
他提到了一個場景:如果有三個請求滑蚯,第一個請求加了分布式鎖,其他二個等待抵栈,在返回前第一個請求當(dāng)機了告材,沒有清除鎖,這種情況怎么辦古劲?
我提到了通過TTL來防止死鎖斥赋;我還提到了用setnx來加鎖,用ttl來設(shè)置存活時間防止死鎖产艾;他提到這是兩個命令疤剑,不是原子的,我回答可以將setnx的value內(nèi)設(shè)置存活時間闷堡,這樣當(dāng)?shù)诙埱髞淼臅r候隘膘,盡管有分布式鎖,但是顯示鎖已經(jīng)過期杠览,所以這個鎖不會生效弯菊;
這個地方有些模糊,需要好好看一下踱阿,有點蒙過去的感覺管钳。
further: 如上我的solution也是會有問題的钦铁,當(dāng)后續(xù)線程并行可能同時檢測到鎖已經(jīng)過期,例如B和C才漆,這樣就會同時執(zhí)行delete操作,然后執(zhí)行set操作牛曹,這時可能c刪除的是B剛剛設(shè)置的鎖,而不是最初的A鎖栽烂。
所以可以這樣躏仇,
1. 用一個更多參數(shù)的set方法,同時有NX和PX語義腺办,即只有當(dāng)不存在才設(shè)置焰手,和同時設(shè)置過期時間在一個原子操作內(nèi),防止客戶端執(zhí)行第一步后宕機怀喉。
2. 兩個語句 - setnx和expire书妻, 當(dāng)setnx失敗的時候,會檢測ttl是否存在躬拢,如果不存在則設(shè)置ttl防止死鎖躲履,這樣即使A線程宕機沒有來得及執(zhí)行expire,也會被后續(xù)線程設(shè)置上聊闯。這樣的side-effect是鎖的持續(xù)時間會比預(yù)期要長些工猜。
TTL過期后,什么時候Redis真正刪除這個緩存菱蔬?
回答不上來篷帅。過后查詢的答案是:Redis使用惰性刪除和定期刪除的策略,惰性刪除是在訪問數(shù)據(jù)時拴泌,首先判斷是否過期魏身,如果過期,則刪除緩存返回為空蚪腐;定期刪除是一定時間內(nèi)對數(shù)據(jù)庫進(jìn)行掃描箭昵,清除掉過期數(shù)據(jù),防止由于數(shù)據(jù)未被訪問而內(nèi)存沒有釋放回季。定期刪除會設(shè)定最大的掃描時間以及每一個數(shù)據(jù)庫抽樣的個數(shù)家制;并且下次掃描會從根據(jù)上次掃描到的數(shù)據(jù)庫繼續(xù)掃描下一個數(shù)據(jù)庫。
如上是刪除過期數(shù)據(jù)泡一,這里是刪除未過期數(shù)據(jù)-當(dāng)內(nèi)存使用達(dá)到maxmemory閾值時慰丛,執(zhí)行maxmemory-policy的策略,一共有6種策略來刪除未過期的數(shù)據(jù)瘾杭。
volatile-lru -> remove the key with an expire set using an LRU algorithm
# allkeys-lru -> remove any key according to the LRU algorithm
# volatile-random -> remove a random key with an expire set
# allkeys-random -> remove a random key, any key
# volatile-ttl -> remove the key with the nearest expire time (minor TTL)
# noeviction -> don't expire at all, just return an error on write operations
volatile指設(shè)置了ttl的元素; allkey指所有元素
lru指least rencently used,去除最近最不常訪問的元素; random指隨機刪除元素哪亿。
ttl指按照ttl優(yōu)先刪除即將過期的元素粥烁。
默認(rèn)是volatile-lru從設(shè)置過期時間的元素里刪除最不長訪問的元素贤笆。
分布式提交
是否用過分布式提交? 我提到二次提交讨阻,面試官說這是傳統(tǒng)辦法芥永,對于互聯(lián)網(wǎng)行業(yè)來說用的比較少,因為性能不夠钝吮。
查詢文檔后埋涧,可以通過消息中間件轉(zhuǎn)為本地事務(wù)。
消息中間件
我提到了kafka奇瘦,
順序存儲是如何實現(xiàn)的棘催?
我說不知道,應(yīng)該是文件的追加寫入耳标,kafka不支持文件的隨機寫入醇坝;
是否知道zero-copy?
我回答的是有點類似堆外內(nèi)存次坡,少了內(nèi)核態(tài)到用戶態(tài)的拷貝呼猪,所以加快速度;另外我還提到了kafka的作弊砸琅,可以直接把一個幾M文件直接返回宋距,從而達(dá)到幾M/s的吞吐量。
有沒有了解push機制的中間件
不會回答
GC
Full GC頻繁症脂,如何查錯谚赎?
我提到首先了解當(dāng)前的配置信息,例如是那種GC collector摊腋,young/old區(qū)的大蟹邪妗;
開啟GC日志來獲取更多信息兴蒸;
dump堆找出異常大或者異常多的可以對象视粮,查看代碼是否有內(nèi)存泄露;
如何寫代碼模擬出Full GC頻繁的現(xiàn)象
我回答 1)調(diào)節(jié)參數(shù)使得young區(qū)很小橙凳,這樣對象直接分配到old區(qū)蕾殴;2)調(diào)節(jié)參數(shù),使得promotion的閾值很小岛啸,甚至為0钓觉,這樣young區(qū)對象直接promote到old區(qū);3)創(chuàng)建大的數(shù)組對象坚踩,因為需要連續(xù)空間荡灾,所以很容易直接分配到堆中;
什么情況下對象會創(chuàng)建在棧內(nèi)?
我提到JVM有優(yōu)化批幌,會把對象打散础锐,將基本數(shù)據(jù)存儲在棧內(nèi);
是否聽說過逃逸分析荧缘?
我回答:判斷一個對象是否可能被其他線程調(diào)用皆警,如果沒有,則說明這個對象時線程安全的截粗,不需要同步信姓,即使有同步也會進(jìn)行同步消除來提高性能。
如何優(yōu)化spark程序绸罗?
1)改變數(shù)據(jù)的處理流程意推;2)充分利用DataFrame的緩存;3)調(diào)優(yōu)參數(shù)
是否遇到數(shù)據(jù)不平衡問題
回答遇到過从诲,舉了分org存儲的實際解決方案左痢。