1.項目中Spring AOP用在什麼地方,爲何這麼用,切點,織入,通知,用本身的話描述一下,AOP原理,動態代理2種實現。html
主要是事務那方面,採用聲明式的事務配置方式,是AOP給你封裝好的。java
通知:node
定義:切面也須要完成工做。在 AOP 術語中,切面的工做被稱爲通知。mysql
工做內容:通知定義了切面是什麼以及什麼時候使用。除了描述切面要完成的工做,通知還解決什麼時候執行這個工做。linux
Spring 切面可應用的 5 種通知類型:web
Before——在方法調用以前調用通知redis
After——在方法完成以後調用通知,不管方法執行成功與否算法
After-returning——在方法執行成功以後調用通知spring
After-throwing——在方法拋出異常後進行通知sql
Around——通知包裹了被通知的方法,在被通知的方法調用以前和調用以後執行自定義的行爲
鏈接點:
定義:鏈接點是一個應用執行過程當中可以插入一個切面的點。 鏈接點能夠是調用方法時、拋出異常時、甚至修改字段時、 切面代碼能夠利用這些點插入到應用的正規流程中 程序執行過程當中可以應用通知的全部點。
切點:
定義:若是通知定義了「什麼」和「什麼時候」。那麼切點就定義了「何處」。切點會匹配通知所要織入的一個或者多個鏈接點。 一般使用明確的類或者方法來指定這些切點。
做用:定義通知被應用的位置(在哪些鏈接點)
切面:
定義:切面是通知和切點的集合,通知和切點共同定義了切面的所有功能——它是什麼,在什麼時候何處完成其功能。
引入: 引入容許咱們向現有的類中添加方法或屬性
織入: 織入是將切面應用到目標對象來建立的代理對象過程。 切面在指定的鏈接點被織入到目標對象中,在目標對象的生命週期中有多個點能夠織入。
AOP原理:面向切面編程,就是把可重用的功能提取出來,而後將這些通用功能在合適的時候織入到應用程序中,好比事務管理、權限控制、日誌記錄、性能統計等。
動態代理的實現:
CGLIB中的動態代理是JDK proxy的一個很好的補充,在JDK中實現代理時,要求代理類必須是繼承接口的類,由於JDK最後生成的proxy class其實就是實現了被代理類所繼承的接口而且繼承了java中的Proxy類,經過反射找到接口的方法,調用InvocationHandler的invoke 方法實現攔截。CGLIb中最後生成的proxy class是一個繼承被代理類的class,經過重寫被代理類中的非final的方法實現代理。
總結爲: JDK proxy:代理類必須實現接口,不須要引來第三方庫
CGLIB: 代理類不能是final,代理的方法也不能是final(繼承限制),針對類實現的代理,必須依賴CGLib類庫。(hibernate中相關的代理採用的是CGLib來執行)。
2.Spring裏面註解用過沒有?autowired 和resource區別
@Resource和@Autowired都是作bean的注入時使用,其實@Resource並非Spring的註解,它的包是javax.annotation.Resource,須要導入,可是Spring支持該註解的注入。
一、共同點
二者均可以寫在字段和setter方法上。二者若是都寫在字段上,那麼就不須要再寫setter方法。
二、不一樣點
(1)@Autowired
@Autowired爲Spring提供的註解,須要導入包org.springframework.beans.factory.annotation.Autowired;只按照byType注入。
@Autowired註解是按照類型(byType)裝配依賴對象,默認狀況下它要求依賴對象必須存在,若是容許null值,能夠設置它的required屬性爲false。若是咱們想使用按照名稱(byName)來裝配,能夠結合@Qualifier註解一塊兒使用。以下:
(2)@Resource
@Resource默認按照ByName自動注入,由J2EE提供,須要導入包javax.annotation.Resource。@Resource有兩個重要的屬性:name和type,而Spring將@Resource註解的name屬性解析爲bean的名字,而type屬性則解析爲bean的類型。
因此,若是使用name屬性,則使用byName的自動注入策略,而使用type屬性時則使用byType自動注入策略。若是既不制定name也不制定type屬性,這時將經過反射機制使用byName自動注入策略。
注:最好是將@Resource放在setter方法上,由於這樣更符合面向對象的思想,經過set、get去操做屬性,而不是直接去操做屬性。
3.Linux命令,怎麼日誌文件裏面找關鍵字
一、查看日誌 前 n行:
cat 文件名 | head -n 數量
demo:
cat test.log | head -n 200 # 查看test.log前200行
二、查看日誌 尾 n行:
cat 文件名 | tail -n 數量
demo:
cat test.log | tail -n 200 # 查看test.log倒數200行
三、根據 關鍵詞 查看日誌 並返回關鍵詞所在行:
方法一:cat 路徑/文件名 | grep 關鍵詞
demo:
cat test.log | grep "http" # 返回test.log中包含http的全部行
方法二:grep -i 關鍵詞 路徑/文件名 (與方法一效果相同,不一樣寫法而已)
demo:
grep -i "http" ./test.log # 返回test.log中包含http的全部行
單個文件可使用vi或vim編輯器打開日誌文件,使用編輯器裏的查找功能。在查看模式下,符號/後面跟關鍵字向下查找,符號?後面跟關鍵字向上查找,按n查找下一個,按N查找上一個。
4.怎麼殺死一個進程
方法1: 經過kill 進程id的方式能夠實現, 首先須要知道進程id, 例如,想要殺死firefox的進程,經過 ps -ef|grep firefox,能夠查到firefox的進程id: 而後經過 kill 3781 就能夠關閉進程了. 補充: 1. kill -9 來強制終止退出, 例如: kill -9 3781 kill -9 -1 終止你擁有的所有進程。
方法2: killall 經過程序的名字,來殺死進程 例如: killall firefox 注意: 該命令可使用 -9 參數來強制殺死進程, killall -9 firefox
方法3: pkill 經過程序的名字, 直接殺死全部進程 例如: pkill firefox
5.MQ,zookeeper,dubbo,redis,是否瞭解分佈式,是否瞭解負載均衡?
MQ 消息隊列(上游--消息隊列--下游) 在高併發環境下,因爲來不及同步處理,請求每每會發生阻塞,好比大量的insert、update之類的請求同時到達mysql,直接致使無數的行鎖和表鎖,從而觸發too many connections錯誤,經過消息隊列,能夠異步處理請求,從而緩解系統壓力。
MQ的不足是: 1)系統更復雜,多了一個MQ組件 2)消息傳遞路徑更長,延時會增長 3)消息可靠性和重複性互爲矛盾,消息不丟不重難以同時保證 4)上游沒法知道下游的執行結果,這一點是很致命的。 調用方實時依賴執行結果的業務場景,請使用調用,而不是MQ。
何時使用MQ
【典型場景一:數據驅動的任務依賴】
什麼是任務依賴,舉個栗子,互聯網公司常常在凌晨進行一些數據統計任務,這些任務之間有必定的依賴關係,好比:
1)task3須要使用task2的輸出做爲輸入
2)task2須要使用task1的輸出做爲輸入 這樣的話,tast1, task2, task3之間就有任務依賴關係,必須task1先執行,再task2執行,載task3執行。
採用MQ解耦: 1)task1準時開始,結束後發一個「task1 done」的消息 2)task2訂閱「task1 done」的消息,收到消息後第一時間啓動執行,結束後發一個「task2 done」的消息 3)task3同理
採用MQ的優勢是:
1)不須要預留buffer,上游任務執行完,下游任務總會在第一時間被執行
2)依賴多個任務,被多個任務依賴都很好處理,只須要訂閱相關消息便可
3)有任務執行時間變化,下游任務都不須要調整執行時間
須要特別說明的是,MQ只用來傳遞上游任務執行完成的消息,並不用於傳遞真正的輸入輸出數據。
【典型場景二:上游不關心執行結果】
上游須要關注執行結果時要用「調用」,上游不關注執行結果時,就可使用MQ了。
舉個栗子,58同城的不少下游須要關注「用戶發佈帖子」這個事件,好比招聘用戶發佈帖子後,招聘業務要獎勵58豆,房產用戶發佈帖子後,房產業務要送2個置頂,二手用戶發佈帖子後,二手業務要修改用戶統計數據。
若是使用調用關係,會致使上下游邏輯+物理依賴嚴重
優化方案是,採用MQ解耦: 1)帖子發佈成功後,向MQ發一個消息 2)哪一個下游關注「帖子發佈成功」的消息,主動去MQ訂閱
其優勢是:1.上游執行時間短,2.上下游邏輯+物理解耦,,模塊之間不相互依賴.3.新增一個下游消息關注方,上游不須要修改任何代碼
典型場景三:上游關注執行結果,但執行時間很長 有時候上游須要關注執行結果,但執行結果時間很長(典型的是調用離線處理,或者跨公網調用),也常用回調網關+MQ來解耦。
舉個栗子,微信支付,跨公網調用微信的接口,執行時間會比較長,但調用方又很是關注執行結果,此時通常怎麼玩呢?
通常採用「回調網關+MQ」方案來解耦:
1)調用方直接跨公網調用微信接口
2)微信返回調用成功,此時並不表明返回成功
3)微信執行完成後,回調統一網關
4)網關將返回結果通知MQ
5)請求方收到結果通知
總結
MQ是一個互聯網架構中常見的解耦利器。
何時不使用MQ? 上游實時關注執行結果
何時使用MQ? 1)數據驅動的任務依賴
2)上游不關心多下游執行結果
3)異步返回執行時間長
zookeeper
1.ZooKeeper是什麼?
ZooKeeper是一個分佈式的,開放源碼的分佈式應用程序協調服務,是Google的Chubby一個開源的實現,它是集羣的管理者,監視着集羣中各個節點的狀態,根據節點提交的反饋進行下一步合理操做。最終,將簡單易用的接口和性能高效、功能穩定的系統提供給用戶
2.ZooKeeper提供了什麼?
1)文件系統
2)通知機制
3.Zookeeper文件系統
每一個子目錄項如 NameService 都被稱做爲znode,和文件系統同樣,咱們可以自由的增長、刪除znode,在一個znode下增長、刪除子znode,惟一的不一樣在於znode是能夠存儲數據的。
有四種類型的znode:
一、PERSISTENT-持久化目錄節點
客戶端與zookeeper斷開鏈接後,該節點依舊存在
二、PERSISTENT_SEQUENTIAL-持久化順序編號目錄節點
客戶端與zookeeper斷開鏈接後,該節點依舊存在,只是Zookeeper給該節點名稱進行順序編號
三、EPHEMERAL-臨時目錄節點
客戶端與zookeeper斷開鏈接後,該節點被刪除
四、EPHEMERAL_SEQUENTIAL-臨時順序編號目錄節點
客戶端與zookeeper斷開鏈接後,該節點被刪除,只是Zookeeper給該節點名稱進行順序編號
4.Zookeeper通知機制
客戶端註冊監聽它關心的目錄節點,當目錄節點發生變化(數據改變、被刪除、子目錄節點增長刪除)時,zookeeper會通知客戶端。
5.Zookeeper作了什麼?
1.命名服務 2.配置管理 3.集羣管理 4.分佈式鎖 5.隊列管理
6.Zookeeper命名服務
在zookeeper的文件系統裏建立一個目錄,即有惟一的path。在咱們使用tborg沒法肯定上游程序的部署機器時便可與下游程序約定好path,經過path即能互相探索發現。
7.Zookeeper的配置管理
程序老是須要配置的,若是程序分散部署在多臺機器上,要逐個改變配置就變得困難。如今把這些配置所有放到zookeeper上去,保存在 Zookeeper 的某個目錄節點中,而後全部相關應用程序對這個目錄節點進行監聽,一旦配置信息發生變化,每一個應用程序就會收到 Zookeeper 的通知,而後從 Zookeeper 獲取新的配置信息應用到系統中就好
8.Zookeeper集羣管理
所謂集羣管理無在意兩點:是否有機器退出和加入、選舉master。
對於第一點,全部機器約定在父目錄GroupMembers下建立臨時目錄節點,而後監聽父目錄節點的子節點變化消息。一旦有機器掛掉,該機器與 zookeeper的鏈接斷開,其所建立的臨時目錄節點被刪除,全部其餘機器都收到通知:某個兄弟目錄被刪除,因而,全部人都知道:它上船了。
新機器加入也是相似,全部機器收到通知:新兄弟目錄加入,highcount又有了,對於第二點,咱們稍微改變一下,全部機器建立臨時順序編號目錄節點,每次選取編號最小的機器做爲master就好。
9.Zookeeper分佈式鎖
有了zookeeper的一致性文件系統,鎖的問題變得容易。鎖服務能夠分爲兩類,一個是保持獨佔,另外一個是控制時序。
對於第一類,咱們將zookeeper上的一個znode看做是一把鎖,經過createznode的方式來實現。全部客戶端都去建立 /distribute_lock 節點,最終成功建立的那個客戶端也即擁有了這把鎖。用完刪除掉本身建立的distribute_lock 節點就釋放出鎖。
對於第二類, /distribute_lock 已經預先存在,全部客戶端在它下面建立臨時順序編號目錄節點,和選master同樣,編號最小的得到鎖,用完刪除,依次方便。
10.Zookeeper隊列管理
兩種類型的隊列:
一、同步隊列,當一個隊列的成員都聚齊時,這個隊列纔可用,不然一直等待全部成員到達。
二、隊列按照 FIFO 方式進行入隊和出隊操做。
第一類,在約定目錄下建立臨時目錄節點,監聽節點數目是不是咱們要求的數目。
第二類,和分佈式鎖服務中的控制時序場景基本原理一致,入列有編號,出列按編號。
11.Zookeeper設計目的
1.最終一致性:client不論鏈接到哪一個Server,展現給它都是同一個視圖,這是zookeeper最重要的性能。
2.可靠性:具備簡單、健壯、良好的性能,若是消息被到一臺服務器接受,那麼它將被全部的服務器接受。
3.實時性:Zookeeper保證客戶端將在一個時間間隔範圍內得到服務器的更新信息,或者服務器失效的信息。但因爲網絡延時等緣由,Zookeeper不能保證兩個客戶端能同時獲得剛更新的數據,若是須要最新數據,應該在讀數據以前調用sync()接口。
4.等待無關(wait-free):慢的或者失效的client不得干預快速的client的請求,使得每一個client都能有效的等待。
5.原子性:更新只能成功或者失敗,沒有中間狀態。
6.順序性:包括全局有序和偏序兩種:全局有序是指若是在一臺服務器上消息a在消息b前發佈,則在全部Server上消息a都將在消息b前被髮布;偏序是指若是一個消息b在消息a後被同一個發送者發佈,a必將排在b前面。
12.Zookeeper工做原理
Zookeeper 的核心是原子廣播,這個機制保證了各個Server之間的同步。實現這個機制的協議叫作Zab協議。Zab協議有兩種模式,它們分別是恢復模式(選主)和廣播模式(同步)。當服務啓動或者在領導者崩潰後,Zab就進入了恢復模式,當領導者被選舉出來,且大多數Server完成了和 leader的狀態同步之後,恢復模式就結束了。狀態同步保證了leader和Server具備相同的系統狀態。
爲了保證事務的順序一致性,zookeeper採用了遞增的事務id號(zxid)來標識事務。全部的提議(proposal)都在被提出的時候加上了zxid。實現中zxid是一個64位的數字,它高32位是epoch用來標識leader關係是否改變,每次一個leader被選出來,它都會有一個新的epoch,標識當前屬於那個leader的統治時期。低32位用於遞增計數。
13.Zookeeper 下 Server工做狀態
每一個Server在工做過程當中有三種狀態:
LOOKING:當前Server不知道leader是誰,正在搜尋
LEADING:當前Server即爲選舉出來的leader
FOLLOWING:leader已經選舉出來,當前Server與之同步
14.Zookeeper選主流程(basic paxos)
當leader崩潰或者leader失去大多數的follower,這時候zk進入恢復模式,恢復模式須要從新選舉出一個新的leader,讓全部的Server都恢復到一個正確的狀態。Zk的選舉算法有兩種:一種是基於basic paxos實現的,另一種是基於fast paxos算法實現的。系統默認的選舉算法爲fast paxos。
1.選舉線程由當前Server發起選舉的線程擔任,其主要功能是對投票結果進行統計,並選出推薦的Server;
2.選舉線程首先向全部Server發起一次詢問(包括本身);
3.選舉線程收到回覆後,驗證是不是本身發起的詢問(驗證zxid是否一致),而後獲取對方的id(myid),並存儲到當前詢問對象列表中,最後獲取對方提議的leader相關信息(id,zxid),並將這些信息存儲到當次選舉的投票記錄表中;
4.收到全部Server回覆之後,就計算出zxid最大的那個Server,並將這個Server相關信息設置成下一次要投票的Server;
5.線程將當前zxid最大的Server設置爲當前Server要推薦的Leader,若是此時獲勝的Server得到n/2 + 1的Server票數,設置當前推薦的leader爲獲勝的Server,將根據獲勝的Server相關信息設置本身的狀態,不然,繼續這個過程,直到leader被選舉出來。 經過流程分析咱們能夠得出:要使Leader得到多數Server的支持,則Server總數必須是奇數2n+1,且存活的Server的數目不得少於n+1. 每一個Server啓動後都會重複以上流程。在恢復模式下,若是是剛從崩潰狀態恢復的或者剛啓動的server還會從磁盤快照中恢復數據和會話信息,zk會記錄事務日誌並按期進行快照,方便在恢復時進行狀態恢復。
redis
Redis是一款開源的、高性能的鍵-值存儲(key-value store)。它常被稱做是一款數據結構服務器(data structure server)。
Redis的鍵是String類型,值能夠包括字符串(strings)類型,同時它還包括哈希(hashes)、列表(lists)、集合(sets)和 有序集合(sorted sets)等數據類型。 對於這些數據類型,你能夠執行原子操做。
爲了得到優異的性能,Redis採用了內存中(in-memory)數據集(dataset)的方式。同時,Redis支持數據的持久化,須要常常將內存中的數據同步到磁盤來保證持久化。
Redis一樣支持主從複製(master-slave replication),而且具備很是快速的非阻塞首次同步( non-blocking first synchronization)、網絡斷開自動重連等功能。同時Redis還具備其它一些特性,其中包括簡單的事物支持、發佈訂閱 ( pub/sub)、管道(pipeline)和虛擬內存(vm)等 。
Redis功能:
持久化:
redis是一個支持持久化的內存數據庫,即redis須要常常將內存中的數據同步到磁盤來保證持久化,這是相對memcache來講的一個大的優點。redis支持兩種持久化方式,一種是 Snapshotting(快照)也是默認方式,另外一種是Append-only file(縮寫aof)的方式。
主從複製:
主從複製容許多個slave server擁有和master server相同的數據庫副本。下面是關於redis主從複製的一些特色
1.master能夠有多個slave。
2.除了多個slave連到相同的master外,slave也能夠鏈接其餘slave造成圖狀結構。
3.主從複製不會阻塞master。也就是說當一個或多個slave與master進行初次同步數據時,master能夠繼續處理client發來的請求。相反slave在初次同步數據時則會阻塞,不能處理client的請求。
4.主從複製能夠用來提升系統的可伸縮性(咱們能夠用多個slave 專門用於client的讀請求,好比sort操做可使用slave來處理),也能夠用來作簡單的數據冗餘。
5.能夠在master禁用數據持久化,只須要註釋掉master 配置文件中的全部save配置,而後只在slave上配置數據持久化。
事務:
redis對事務的支持目前還比較簡單。redis只能保證一個client發起的事務中的命令能夠連續的執行,而中間不會插入其餘client的命令。
Multi 事物開始
Exec 執行事務
Discard 放棄事物
Watch 監聽key
Unwatch 放棄全部key的監聽
watch 命令會監視給定的key,當exec時候若是監視的key從調用watch後發生過變化,則整個事務會失敗。注意watch的key是對整個鏈接有效的,和事務同樣,若是鏈接斷開,監視和事務都會被自動清除。
發佈訂閱:
發佈訂閱(pub/sub)是一種消息通訊模式。訂閱者能夠經過subscribe和psubscribe命令向redis server訂閱本身感興趣的消息類型,redis將消息類型稱爲通道(channel)。當發佈者經過publish命令向redis server發送特定類型的消息時。訂閱該消息類型的所有client都會收到此消息。這裏消息的傳遞是多對多的。一個client能夠訂閱多個 channel,也能夠向多個channel發送消息。
Subscribe
Unsubscribe
Psubscribe
Punsubscribe
Publish
管道:
redis是一個cs模式的tcp server,使用和http相似的請求響應協議。一個client能夠經過一個socket鏈接發起多個請求命令。每一個請求命令發出後client一般 會阻塞並等待redis服務處理,redis處理完後請求命令後會將結果經過響應報文返回給client。
虛擬內存:
redis沒有使用os提供的虛擬內存機制而是本身實現了本身的虛擬內存機制 ,可是思路和目的都是相同的。就是暫時把不常常訪問的數據從內存交換到磁盤中,從而騰出內存空間用於其餘須要訪問的數據。
Redis應用場景:
1.取最新N個數據的操做
好比典型的取你網站的最新文章,經過下面方式,咱們能夠將最新的5000條評論的ID放在Redis的List集合中,並將超出集合部分從數據庫獲取
使用LPUSH latest.comments<ID>命令,向list集合中插入數據
插入完成後再用LTRIM latest.comments 0 5000命令使其永遠只保存最近5000個ID
而後咱們在客戶端獲取某一頁評論時能夠用下面的邏輯(僞代碼)
FUNCTION get_latest_comments(start,num_items):
id_list = redis.lrange("latest.comments",start,start+num_items-1)
IF id_list.length < num_items
id_list = SQL_DB("SELECT ... ORDER BY time LIMIT ...")
END
RETURN id_list
END
若是你還有不一樣的篩選維度,好比某個分類的最新N條,那麼你能夠再建一個按此分類的List,只存ID的話,Redis是很是高效的。
2.排行榜應用,取TOP N操做
這個需求與上面需求的不一樣之處在於,前面操做以時間爲權重,這個是以某個條件爲權重,好比按頂的次數排序,這時候就須要咱們的sorted set出馬了,將你要排序的值設置成sorted set的score,將具體的數據設置成相應的value,每次只須要執行一條ZADD命令便可。
3.須要精準設定過時時間的應用
好比你能夠把上面說到的sorted set的score值設置成過時時間的時間戳,那麼就能夠簡單地經過過時時間排序,定時清除過時數據了,不只是清除Redis中的過時數據,你徹底能夠把Redis裏這個過時時間當成是對數據庫中數據的索引,用Redis來找出哪些數據須要過時刪除,而後再精準地從數據庫中刪除相應的記錄。
4.計數器應用
Redis的命令都是原子性的,你能夠輕鬆地利用INCR,DECR命令來構建計數器系統。
5.Uniq操做,獲取某段時間全部數據排重值
這個使用Redis的set數據結構最合適了,只須要不斷地將數據往set中扔就好了,set意爲集合,因此會自動排重。
6.實時系統,反垃圾系統
經過上面說到的set功能,你能夠知道一個終端用戶是否進行了某個操做,能夠找到其操做的集合並進行分析統計對比等。沒有作不到,只有想不到。
7.Pub/Sub構建實時消息系統
Redis的Pub/Sub系統能夠構建實時的消息系統,好比不少用Pub/Sub構建的實時聊天系統的例子。
8.構建隊列系統
使用list能夠構建隊列系統,使用sorted set甚至能夠構建有優先級的隊列系統。
9.緩存
這個沒必要說了,性能優於Memcached(在某些方面,並非全面優於),數據結構更多樣化。
Redis總結:
Redis使用最佳方式是所有數據in-memory。
Redis更多場景是做爲Memcached的替代者來使用。
當須要除key/value以外的更多數據類型支持時,使用Redis更合適。
當存儲的數據不能被剔除時,使用Redis更合適。(持久化)
對數據高併發讀寫
對海量數據的高效率存儲和訪問
對數據的高可擴展性和高可用性(分佈式)
redis和memcached的區別:
1 Redis不只僅支持簡單的k/v類型的數據,同時還提供list,set,hash等數據結構的存儲。
2 Redis支持數據的備份,即master-slave模式的數據備份。
3 Redis支持數據的持久化,能夠將內存中的數據保持在磁盤中,重啓的時候能夠再次加載進行使用。
4 memcache掛掉後,數據不可恢復; redis數據丟失後能夠經過aof恢復
在Redis中,並非全部的數據都一直存儲在內存中的。這是和Memcached相比一個最大的區別(我我的是這麼認爲的)。
負載均衡
當一臺服務器的性能達到極限時,咱們可使用服務器集羣來提升網站的總體性能。那麼,在服務器集羣中,須要有一臺服務器充當調度者的角色,用戶的全部請求都會首先由它接收,調度者再根據每臺服務器的負載狀況將請求分配給某一臺後端服務器去處理。 那麼在這個過程當中,調度者如何合理分配任務,保證全部後端服務器都將性能充分發揮,從而保持服務器集羣的總體性能最優,這就是負載均衡問題。
負載均衡算法
一、輪詢法
將請求按順序輪流地分配到後端服務器上,它均衡地對待後端的每一臺服務器,而不關心服務器實際的鏈接數和當前的系統負載。
二、隨機法
經過系統的隨機算法,根據後端服務器的列表大小值來隨機選取其中的一臺服務器進行訪問。由機率統計理論能夠得知,隨着客戶端調用服務端的次數增多,
其實際效果愈來愈接近於平均分配調用量到後端的每一臺服務器,也就是輪詢的結果。
三、源地址哈希法
源地址哈希的思想是根據獲取客戶端的IP地址,經過哈希函數計算獲得的一個數值,用該數值對服務器列表的大小進行取模運算,獲得的結果即是客服端要訪問服務器的序號。採用源地址哈希法進行負載均衡,同一IP地址的客戶端,當後端服務器列表不變時,它每次都會映射到同一臺後端服務器進行訪問。
四、加權輪詢法
不一樣的後端服務器可能機器的配置和當前系統的負載並不相同,所以它們的抗壓能力也不相同。給配置高、負載低的機器配置更高的權重,讓其處理更多的請;而配置低、負載高的機器,給其分配較低的權重,下降其系統負載,加權輪詢能很好地處理這一問題,並將請求順序且按照權重分配到後端。
五、加權隨機法
與加權輪詢法同樣,加權隨機法也根據後端機器的配置,系統的負載分配不一樣的權重。不一樣的是,它是按照權重隨機請求後端服務器,而非順序。
六、最小鏈接數法
最小鏈接數算法比較靈活和智能,因爲後端服務器的配置不盡相同,對於請求的處理有快有慢,它是根據後端服務器當前的鏈接狀況,動態地選取其中當前積壓鏈接數最少的一臺服務器來處理當前的請求,儘量地提升後端服務的利用效率,將負責合理地分流到每一臺服務器。
id全局自增如何實現?
treemap
如何設計一個循環隊列?
構造方法 :設置隊列長度
Front()從隊首獲取元素
Rear()從隊尾獲取元素
enQueue()向循環隊列插入一個元素
deQueue()向循環隊列刪除一個元素
isEmpty()檢查循環隊列是否爲空
isFull()檢查循環隊列是否已滿
jdbc鏈接數據庫的流程:
JDBC流程:
第一步:加載Driver類,註冊數據庫驅動;
第二步:經過DriverManager,使用url,用戶名和密碼創建鏈接(Connection);
第三步:經過Connection,使用sql語句打開Statement對象;
第四步:執行語句,將結果返回resultSet;
第五步:對結果resultSet進行處理;
第六步:倒敘釋放資源resultSet-》preparedStatement-》connection。
抽象類和接口的使用場景:
抽象類:
1. 你想要在幾個關聯緊密的類之間共享代碼。
2. 你想要繼承抽象類的那些類有一些公共方法或屬性抑或是有修改protected或private屬性的權限。這時你也能夠考慮使用抽象類。
3. 你想要聲明非靜態或者是非最終執行的屬性。你能夠得到而且修改這些屬性所屬的對象的狀態。
接口:
1. 用相互之間無關的類實現你的接口。舉例來講,可比較的和可克隆的那些接口可使用無關的類來實現。
2. 你想指定一個特定數據類型的行爲,可是不用去關心由誰來實現這一行爲。
3. 你想要利用多繼承的優點。
spring boot和spring的區別
想了解區別,其實就是Spring Boot提供了哪些特徵:
1.Spring Boot能夠創建獨立的Spring應用程序;
2.內嵌瞭如Tomcat,Jetty和Undertow這樣的容器,也就是說能夠直接跑起來,用不着再作部署工做了。
3.無需再像Spring那樣搞一堆繁瑣的xml文件的配置;
4.能夠自動配置Spring;
5.提供了一些現有的功能,如量度工具,表單數據驗證以及一些外部配置這樣的一些第三方功能;
6.提供的POM能夠簡化Maven的配置;
spring boot和spring cloud的區別
一、Spring boot 是 Spring 的一套快速配置腳手架,能夠基於spring boot 快速開發單個微服務;Spring Cloud是一個基於Spring Boot實現的雲應用開發工具;
二、Spring boot專一於快速、方便集成的單個個體,Spring Cloud是關注全局的服務治理框架;
三、spring boot使用了默認大於配置的理念,不少集成方案已經幫你選擇好了,能不配置就不配置,Spring Cloud很大的一部分是基於Spring boot來實現。
四、Spring boot能夠離開Spring Cloud獨立使用開發項目,可是Spring Cloud離不開Spring boot,屬於依賴的關係。
springcloud包含服務註冊、發現、熔斷等功能 。
爲何須要springcloud?一個服務編寫好後,一啓動就會自動註冊到服務中心,調用方只管向服務中心發送服務的名稱和參數,根本不關注服務的路徑。springboot就是作服務的工具,springcloud是管理服務運行的工具。
spring mvc和三層架構的區別
MVC是一種設計模式,其實現有Struts、SPringMVC等,三層架構主要有數據訪問層、業務層、展示層,其展示層能夠用MVC模式,數據訪問層能夠用Hibernate,該層所作事務直接操做數據庫、業務層就是寫本身業務的地方了,是針對數據層的操做。
Spring的出現,下降了三層架構的耦合,達到解耦的目的(固然Spring的做用還有不少),因此,如今就流行SSH、S2SH之類的。
歸併排序思想和代碼
兩路歸併排序算法思路:
分而治之(divide - conquer);每一個遞歸過程涉及三個步驟
第一, 分解: 把待排序的 n 個元素的序列分解成兩個子序列, 每一個子序列包括 n/2 個元素.
第二, 治理: 對每一個子序列分別調用歸併排序MergeSort, 進行遞歸操做
第三, 合併: 合併兩個排好序的子序列,生成排序結果.
代碼實現
public
static
int
[] sort(
int
[] a,
int
low,
int
high){
int
mid = (low+high)/
2
;
if
(low<high){
sort(a,low,mid);
sort(a,mid+
1
,high);
//左右歸併
merge(a,low,mid,high);
}
return
a;
}
public
static
void
merge(
int
[] a,
int
low,
int
mid,
int
high) {
int
[] temp =
new
int
[high-low+
1
];
int
i= low;
int
j = mid+
1
;
int
k=
0
;
// 把較小的數先移到新數組中
while
(i<=mid && j<=high){
if
(a[i]<a[j]){
temp[k++] = a[i++];
}
else
{
temp[k++] = a[j++];
}
}
// 把左邊剩餘的數移入數組
while
(i<=mid){
temp[k++] = a[i++];
}
// 把右邊邊剩餘的數移入數組
while
(j<=high){
temp[k++] = a[j++];
}
// 把新數組中的數覆蓋nums數組
for
(
int
x=
0
;x<temp.length;x++){
a[x+low] = temp[x];
}
}
aqs 獨佔鎖 共享鎖 公平鎖 非公平鎖
簡介
AQS實現鎖機制並非經過synchronized——給對象加鎖實現的,事實上它僅僅是一個工具類!它沒有使用更高級的機器指令,也不靠關鍵字,更不依靠JDK編譯時的特殊處理,僅僅做爲一個普普統統的類就完成了代碼塊的訪問控制。
AQS使用標記位+隊列的方式(FIFO隊列),記錄獲取鎖、競爭鎖、釋放鎖等一些類鎖操做。但更準確的說,AQS並不關心什麼是鎖,對於AQS來講它只是實現了一系列的用於判斷資源是否能夠訪問的API,而且封裝了在訪問資源受限時,將請求訪問的線程加入隊列、掛起、喚醒等操做。AQS關心的問題以下:
1.資源不可訪問時,怎麼處理?
2.資源時能夠被同時訪問,仍是在同一時間只能被一個線程訪問?
3.若是有線程等不及資源了,怎麼從AQS隊列中退出?
至於資源可否被訪問的問題,則交給子類去實現。
站在使用者的角度,AQS的功能主要分爲兩類:獨佔鎖和共享鎖。在它的全部子類中,要麼實現了它的獨佔功能的API,要麼實現了共享功能的API,但不會同時使用兩套API,即便是ReentrantReadWriteLock,也是經過兩個內部類:讀鎖和寫鎖,分別使用兩套API來實現的。
當AQS的子類實現獨佔功能時,如ReentrantLock,資源是否能夠被訪問被定義爲:只要AQS的state變量不爲0,而且持有鎖的線程不是當前線程,那麼表明資源不可訪問。
當AQS的子類實現共享功能時,如CountDownLatch,資源是否能夠被訪問被定義爲:只要AQS的state變量不爲0,那麼表明資源不能夠爲訪問。
ReentrantLock會保證在同一時間有且只有一個線程獲取到鎖,其他線程所有掛起,直到該擁有鎖的線程釋放鎖,被掛起的線程被喚醒從新開始競爭鎖。
ReentrantLock的加鎖所有委託給內部代理類完成,ReentrantLock只是封裝了統一的一套API而已,而ReentrantLock又分爲公平鎖和非公平鎖。
公平鎖:每一個線程搶佔鎖的順序爲前後調用lock方法的順序,並依此順序得到鎖,相似於排隊吃飯;
非公平鎖:每一個線程搶佔鎖的順序不變,誰運氣好,誰就得到鎖,和調用lock方法的前後順序無關,相似後插入。
非公平鎖的lock方法的處理方式:在lock的時候先直接CAS修改一次state變量(嘗試獲取鎖),成功就返回,不成功再排隊,從而達到不排隊直接搶佔的目的。
而對於公平鎖:則是老老實實的開始就走AQS的流程排隊獲取鎖。若是前面有人調用過其lock方法,則排在隊列中前面,也就更有機會更早的獲取鎖,從而達到「公平」的目的。
共享鎖與獨佔鎖的對比
與AQS的獨佔功能同樣,共享鎖是否能夠被獲取的判斷爲空方法,交由子類去實現。
與AQS的獨佔功能不一樣,當鎖被頭節點獲取後,獨佔功能是隻有頭節點獲取鎖,其他節點的線程繼續沉睡,等待鎖被釋放後,纔會喚醒下一個節點的線程,而共享功能是隻要頭節點獲取鎖成功,就在喚醒自身節點對應的線程的同時,繼續喚醒AQS隊列中的下一個節點的線程,每一個節點在喚醒自身的同時還會喚醒下一個節點對應的線程,以實現共享狀態的「向後傳播」,從而實現共享功能。
synchronized可重入怎麼實現
可重入:
若一個程序或子程序能夠「在任意時刻被中斷而後操做系統調度執行另一段代碼,這段代碼又調用了該子程序不會出錯」,則稱其爲可重入(reentrant或re-entrant)的。
即當該子程序正在運行時,執行線程能夠再次進入並執行它,仍然得到符合設計時預期的結果。與多線程併發執行的線程安全不一樣,可重入強調對單個線程執行時從新進入同一個子程序仍然是安全的。
咱們回來看synchronized,synchronized擁有強制原子性的內部鎖機制,是一個可重入鎖。所以,在一個線程使用synchronized方法時調用該對象另外一個synchronized方法,即一個線程獲得一個對象鎖後再次請求該對象鎖,是永遠能夠拿到鎖的。
在Java內部,同一個線程調用本身類中其餘synchronized方法/塊時不會阻礙該線程的執行,同一個線程對同一個對象鎖是可重入的,同一個線程能夠獲取同一把鎖屢次,也就是能夠屢次重入。緣由是Java中線程得到對象鎖的操做是以線程爲單位的,而不是以調用爲單位的。
以前談到過,每一個鎖關聯一個線程持有者和一個計數器。當計數器爲0時表示該鎖沒有被任何線程持有,那麼任何線程都均可能得到該鎖而調用相應方法。當一個線程請求成功後,JVM會記下持有鎖的線程,並將計數器計爲1。此時其餘線程請求該鎖,則必須等待。而該持有鎖的線程若是再次請求這個鎖,就能夠再次拿到這個鎖,同時計數器會遞增。當線程退出一個synchronized方法/塊時,計數器會遞減,若是計數器爲0則釋放該鎖。
手寫一個線程安全的生產者和消費者
import java.util.*;
public class consumer {
/**
* @param args
*/
//消費者
private List<Integer> queue;
public consumer(List<Integer> queue){
this.queue=queue;
}
public void run(){
try{
while(true){
if(Thread.currentThread().isInterrupted()) break;
synchronized(queue){
if(queue.size()==0){
queue.wait();
queue.notifyAll();
}
int data=queue.remove(0);
}
Thread.sleep(1000);
}
}catch(InterruptedException e){
e.printStackTrace();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
//生產者
class Producer implements Runnable {
private List<Integer> queue;
private int length;
public Producer(List<Integer> queue, int length) {
this.queue = queue;
this.length = length;
}
@Override
public void run() {
try {
while (true) {
if (Thread.currentThread().isInterrupted())
break;
Random r = new Random();
long data = r.nextInt(100);
synchronized (queue) {
if (queue.size() >= length) {
queue.notifyAll();
queue.wait();
} else
queue.add(data);
}
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
java中的io
字節輸入流:InputStream
字節輸出流:OutputStream
字符輸入流:Reader
字符輸出流:Writer
linux如何查找某個目標字符串在文件的哪一行
grep -n "xxx" file 其中xxx爲要查找的字符串,file爲文件名
tcp與udp的應用場景
注重通訊的實時性與可靠性應該選用tcp 如文件傳輸、重要狀態的更新,郵件、瀏覽器等
注重通訊數據的完整性以及速度時應該選用udp 如視頻傳輸、實時通訊等。
spring中bean的生命週期:
apache和tomcat的區別
1.apache是web服務器,tomcat是應用(java)服務器,它只是一個servlet(jsp也翻譯成servlet)容器,能夠認爲是apache的擴展。
2..apache和tomcat均可以作爲獨立的web服務器來運行。可是apache不能解釋java程序(jsp,serverlet)
3.Apache是普通服務器,自己只支持html即普通網頁。不過能夠經過插件支持PHP,還能夠與Tomcat連通(單向Apache鏈接Tomcat,就是說經過Apache能夠訪問Tomcat資源。反之否則)
4.二者都是一種容器,只不過發佈的東西不一樣。apache是html容器,功能像IIS同樣,tomcat是jsp/servlet容器,用於發佈JSP及JAVA的,相似的有IBM的webshere、EBA的Weblogic,sun的JRun等
5.apache和tomcat是獨立的,在同一臺服務器上能夠集成。
數據庫查詢變慢了怎麼辦?
1.根據查詢條件,創建索引;
2.優化查詢程序;
3.提升網速;
4.擴大服務器的內存;
5.若可能增長服務器CPU個數;
6.分庫分表
數據切分就是將數據分散存儲到多個數據庫中,使得單一數據庫中的數據量變小,經過擴充主機的數量緩解單一數據庫的性能問題,從而達到提高數據庫操做性能的目的。
object類的結構
內存泄露的例子
內存泄漏:申請內存後,沒法釋放已申請的空間,無用對象持續佔有內存得不到及時釋放。
1.靜態集合類:靜態集合類生命週期和應用程序同樣長。
2.監聽器:在釋放的時候沒有刪除監聽器
3.物理鏈接:數據庫鏈接和網絡鏈接,除非顯式關閉,不然不會自動被gc回收
4.內部類
5.單例模式:單例對象持有一個外部對象的引用,那麼這個外部對象就不會被回收。
group by子句使用注意事項
當查詢中存在group by子句時,select列表(或是having子句)中只能存在分組函數,或是出如今group by子句中的字段。 分組函數:max,min,sum,avg,count。
滑動窗口和擁塞控制