面試:第四章:項(xiàng)目介紹

哪些情況用到activeMq?

商品上架后更新ES索引庫、更新靜態(tài)頁、發(fā)送短信

提交訂單后清除購物車中的數(shù)據(jù)

支付未完成時(shí)支付完成后修改訂單狀態(tài)
秒殺的時(shí)候,只有最后一件物品,該怎么去搶或者分配?

秒殺商品的庫存都會(huì)放到redis緩存中,在客戶下單時(shí)就減庫存,我們設(shè)置庫存庫存閘值,用于某些商品數(shù)量非單件不可分割,減完庫存會(huì)判斷庫存是否為大于庫存閘值,如果小于,表示庫存不足,剛才減去的數(shù)量再恢復(fù),整個(gè)過程使用redis的watch鎖 。
你項(xiàng)目對(duì)于訂單是怎么處理的,假如一個(gè)客戶在下訂單的時(shí)候沒有購買怎么辦?

訂單表中設(shè)置了一個(gè)過期時(shí)間,每天會(huì)有定時(shí)任務(wù)來掃描訂單表數(shù)據(jù),如果到達(dá)預(yù)訂的過期時(shí)間沒有付款就會(huì)取消此訂單交易。
對(duì)于顧客在購買商品的時(shí)候你們怎么處理你們的庫存?

普通商品只有在發(fā)貨時(shí)才去更新庫存,如果庫存不足商家會(huì)馬上補(bǔ)貨

秒殺的商品會(huì)在客戶下單時(shí)就減庫存,如果在規(guī)定時(shí)間(半個(gè)小時(shí))沒有付款,會(huì)取消此訂單把庫存還原。
秒殺系統(tǒng)中如何防止超售?如何避免腳本進(jìn)行惡意刷單?

防止超售解決方案:將存庫從MySQL前移到Redis中,所有的寫操作放到內(nèi)存中,由于Redis中不存在鎖故不會(huì)出現(xiàn)互相等待,并且由于Redis的寫性能和讀性能都遠(yuǎn)高于MySQL,這就解決了高并發(fā)下的性能問題。然后通過隊(duì)列等異步手段,將變化的數(shù)據(jù)異步寫入到DB中。當(dāng)達(dá)到庫存閥值的時(shí)候就不在消費(fèi)隊(duì)列,并關(guān)閉購買功能。避免腳本惡意刷單:采用IP級(jí)別的限流,即針對(duì)某一個(gè)IP,限制單位時(shí)間內(nèi)發(fā)起請求數(shù)量。
單點(diǎn)登錄你們是自己編寫的還是使用通用的CAS?

項(xiàng)目使用通用的CAS框架。
什么是CAS?

中央認(rèn)證服務(wù),企業(yè)級(jí)單點(diǎn)登錄解決方案。CAS Server 需要獨(dú)立部署,主要負(fù)責(zé)對(duì)用戶的認(rèn)證工作;CAS Client 負(fù)責(zé)處理對(duì)客戶端受保護(hù)資源的訪問請求,需要登錄時(shí),重定向到 CAS Server。
如果一個(gè)用戶的token被其他用戶劫持了,怎樣解決這個(gè)安全問題。

a、在存儲(chǔ)的時(shí)候把token進(jìn)行對(duì)稱加密存儲(chǔ),用時(shí)解開。
b、將請求URL、時(shí)間戳、token三者進(jìn)行合并加鹽簽名,服務(wù)端校驗(yàn)有效性。

c.HTTPS對(duì)URL進(jìn)行加密
對(duì)系統(tǒng)運(yùn)行造成很大壓力,隨著項(xiàng)目上線時(shí)間增長,壓力會(huì)越來越大,我們怎么減輕系統(tǒng)訪問壓力

流量分為三種,一種是商家流量,另一種是用戶流量,第三種運(yùn)營商流量。

解決方案:

      這三種流量對(duì)系統(tǒng)運(yùn)行造成很大壓力,隨著項(xiàng)目上線時(shí)間增長,壓力會(huì)越來越大,因此我們要減輕系統(tǒng)訪問壓力 ,就需要做一系列優(yōu)化措施。

 具體優(yōu)化如下:
 數(shù)據(jù)層面的優(yōu)化:

從數(shù)據(jù)庫層面做優(yōu)化,比如:索引,緩存集群雙緩存,把查詢獨(dú)立出來讀寫分離,配置數(shù)據(jù)庫集群主從復(fù)制,使用Mycat分表,分庫。

從數(shù)據(jù)庫設(shè)計(jì)層面的優(yōu)化:比如減少表關(guān)聯(lián),加入冗余字段

從緩存方面優(yōu)化:比如redis實(shí)現(xiàn)數(shù)據(jù)緩存,減輕數(shù)據(jù)庫壓力

從搜索上進(jìn)行優(yōu)化:比如查找索引庫,使用es或solr全文搜索
項(xiàng)目層面的優(yōu)化:

采用面向服務(wù)的分布式架構(gòu):分擔(dān)服務(wù)器壓力 ,提高項(xiàng)目并發(fā)量。比如dubbox+zookeeper的SOA分布式架構(gòu)

采用分布式文件系統(tǒng)實(shí)現(xiàn)海量文件存儲(chǔ):如采用fastdfs實(shí)現(xiàn)海量圖片存儲(chǔ),提高文件的訪問速度。

采用mq使用服務(wù)進(jìn)一步解藕:同步索引庫,同步靜態(tài)資源,短信發(fā)送
服務(wù)器層面的優(yōu)化

集群思想的使用:tomcat,zookeeper,redis,mysql等

Tomcat異步通信的使用,tomcat連接池配置
秒殺和團(tuán)購業(yè)務(wù)實(shí)現(xiàn)思路

將商品數(shù)量查詢出存入到redis中,所有用戶下單后,減掉redis中的數(shù)量

如果并發(fā)量很大時(shí),還要考慮高并發(fā)問題,所以可以加入mq消息中間件處理搶單問題,再結(jié)合redis實(shí)現(xiàn)庫存減少操作。高并發(fā)方面還可以考慮CDN,Nginx負(fù)載均衡等
你們項(xiàng)目中使用的安全框架是什么?

第一種:使用springSecurity

 

第二種:使用shiro(配置一下再用一下標(biāo)簽就行了),校驗(yàn)用戶登錄和用戶權(quán)限!
項(xiàng)目中使用到的應(yīng)用服務(wù)器是什么?

Tomcat+nginx
項(xiàng)目中遇到什么問題?
ES高亮不能顯示的問題

前臺(tái)使用angularJS加載搜索結(jié)果,但是發(fā)現(xiàn)高亮不能展示。

問題原因:angularJS底層使用ajax,異步加載高亮信息返回給頁面后,頁面沒有刷新,就直接顯示返回的數(shù)據(jù)。此時(shí)會(huì)把所有的數(shù)據(jù)作為普通的文本數(shù)據(jù)進(jìn)行加載。因此就沒有高亮的效果。

解決方案:使用angularJS過濾器過濾文本數(shù)據(jù),此時(shí)angularJS過濾器把html文本數(shù)據(jù)解析為瀏覽器能識(shí)別的html標(biāo)簽。高亮就能展示了。
activeMQ存在運(yùn)行時(shí)間長了以后,收不到消息的現(xiàn)象。時(shí)間長了就會(huì)出現(xiàn),卡死,新的數(shù)據(jù)不能從隊(duì)列接聽到。只能重啟程序。

解決方案:

1)不要頻繁的建立和關(guān)閉連接:JMS使用長連接方式,一個(gè)程序,只要和JMS服務(wù)器保持一個(gè)連接就可以了,不要頻繁的建立和關(guān)閉連接。頻繁的建立和關(guān)閉連接,對(duì)程序的性能影響還是很大的。這一點(diǎn)和jdbc還是不太一樣的。

2)Connection的start()和stop()方法代價(jià)很高:JMS的Connection的start()和stop()方法代價(jià)很高,不能經(jīng)常調(diào)用。我們試用的時(shí)候,寫了個(gè)jms的connection pool,每次將connection取出pool時(shí)調(diào)用start()方法,歸還時(shí)調(diào)用stop()方法,然而后來用jprofiler發(fā)現(xiàn),一般的cpu時(shí)間都耗在了這兩個(gè)方法上。

3)start()后才能收消息:Connection的start()方法調(diào)用后,才能收到j(luò)ms消息。如果不調(diào)用這個(gè)方法,能發(fā)出消息,但是一直收不到消息。不知道其它的jms服務(wù)器也是這樣。

4)顯式關(guān)閉Session:如果忘記了最后關(guān)閉Connection或Session對(duì)象,都會(huì)導(dǎo)致內(nèi)存泄漏。這個(gè)在我測試的時(shí)候也發(fā)現(xiàn)了。本來以為關(guān)閉了Connection,由這個(gè)Connection生成的Session也會(huì)被自動(dòng)關(guān)閉,結(jié)果并非如此,Session并沒有關(guān)閉,導(dǎo)致內(nèi)存泄漏。所以一定要顯式的關(guān)閉Connection和Session。

5)對(duì)Session做對(duì)象池:對(duì)Session做對(duì)象池,而不是Connection。Session也是昂貴的對(duì)象,每次使用都新建和關(guān)閉,代價(jià)也非常高。而且后來我們發(fā)現(xiàn),原來Connection是線程安全的,而Session不是,所以后來改成了對(duì)Session做對(duì)象池,而只保留一個(gè)Connection。

6) 集群:ActiveMQ有強(qiáng)大而靈活的集群功能,但是使用起來還是會(huì)有很多陷阱
activeMQ存在發(fā)出消息太大,造成消息接受不成功。多個(gè)線程從activeMQ中取消息,隨著業(yè)務(wù)的擴(kuò)大,該機(jī)器占用的網(wǎng)絡(luò)帶寬越來越高。

仔細(xì)分析發(fā)現(xiàn),mq入隊(duì)時(shí)并沒有異常高的網(wǎng)絡(luò)流量,僅僅在出隊(duì)時(shí)會(huì)產(chǎn)生很高的網(wǎng)絡(luò)流量。

最終發(fā)現(xiàn)是spring的jmsTemplate與activemq的prefetch機(jī)制配合導(dǎo)致的問題。

研究源碼發(fā)現(xiàn)jmsTemplate實(shí)現(xiàn)機(jī)制是:每次調(diào)用receive()時(shí)都會(huì)創(chuàng)建一個(gè)新的consumer對(duì)象,用完即銷毀。

正常情況下僅僅會(huì)浪費(fèi)重復(fù)創(chuàng)建consumer的資源代價(jià),并不至于產(chǎn)生正常情況十倍百倍的網(wǎng)絡(luò)流量。

但是activeMQ有一個(gè)提高性能的機(jī)制prefetch,此時(shí)就會(huì)有嚴(yán)重的問題。

prefetch機(jī)制:
每次consumer連接至MQ時(shí),MQ預(yù)先存放許多message到消費(fèi)者(前提是MQ中存在大量消息),預(yù)先存 放message的數(shù)量取決于prefetchSize(默認(rèn)為1000)。此機(jī)制的目的很顯然,是想讓客戶端代碼用一個(gè)consumer反復(fù)進(jìn)行 receive操作,這樣能夠大量提高出隊(duì)性能。

此機(jī)制與jmsTemplate配合時(shí)就會(huì)產(chǎn)生嚴(yán)重的問題,每次jmsTemplate.receive(),都會(huì)產(chǎn)生1000個(gè)消息的網(wǎng)絡(luò)流量, 但是因?yàn)閖msTemplae并不會(huì)重用consumer,導(dǎo)致后面999個(gè)消息都被廢棄。反復(fù)jmsTemplate.receive()時(shí),表面上看 不出任何問題,其實(shí)網(wǎng)絡(luò)帶寬會(huì)造成大量的浪費(fèi)。
解決方案:

1、若堅(jiān)持使用jmsTemplate,需要設(shè)置prefetch值為1,相當(dāng)于禁用了activeMQ的prefetch機(jī)制,此時(shí)感覺最健壯, 就算多線程,反復(fù)調(diào)用jmsTemplate.receive()也不會(huì)有任何問題。但是會(huì)有資源浪費(fèi),因?yàn)橐磸?fù)創(chuàng)建consumer并頻繁與服務(wù)器進(jìn) 行數(shù)據(jù)通信,但在性能要求不高的應(yīng)用中也不算什么問題。

2、不使用jmsTemplate,手工創(chuàng)建一個(gè)consumer,并單線程反復(fù)使用它來receive(),此時(shí)可以充分利用prefetch機(jī)制。配合多線程的方式每個(gè)線程擁有自己的一個(gè)consumer,此時(shí)能夠充分發(fā)揮MQ在大吞吐量時(shí)的速度優(yōu)勢。

切記避免多線程使用一個(gè)consumer造成的消息混亂。大吞吐量的應(yīng)用推薦使用方案2,能夠充分利用prefetch機(jī)制提高系MQ的吞吐性能。
商品的價(jià)格變化后,如何同步redis中數(shù)以百萬計(jì)的購物車數(shù)據(jù)。

解決方案:購物車只存儲(chǔ)商品id,到購物車結(jié)算頁面將會(huì)從新查詢購物車數(shù)據(jù),因此就不會(huì)涉及購物車商品價(jià)格同步的問題。
系統(tǒng)中的錢是如何保證安全的。

在當(dāng)前互聯(lián)網(wǎng)系統(tǒng)中錢的安全是頭等大事,如何保證錢的安全可以從以下2個(gè)方面來思考:

1)錢計(jì)算方面

在系統(tǒng)中必須是浮點(diǎn)數(shù)計(jì)算類型存儲(chǔ)錢的額度,否則計(jì)算機(jī)在計(jì)算時(shí)可能會(huì)損失精度。

2)事務(wù)處理方面

在當(dāng)前環(huán)境下,高并發(fā)訪問,多線程,多核心處理下,很容易出現(xiàn)數(shù)據(jù)一致性問題,此時(shí)必須使用事務(wù)進(jìn)行控制,訪問交易出現(xiàn)安全性的問題,那么在分布式系統(tǒng)中,存在分布式事務(wù)問題,可以有很多解決方案:

使用 jpa可以解決

使用 tcc 框架可以解決等等。
訂單中的事物是如何保證一致性的。

使用分布式事務(wù)來進(jìn)行控制,保證數(shù)據(jù)最終結(jié)果的一致性。
講講angularJS四大特征?
MVC 模式

Model:數(shù)據(jù),其實(shí)就是angular變量($scope.XX);

View: 數(shù)據(jù)的呈現(xiàn),Html+Directive(指令);

Controller:操作數(shù)據(jù),就是function,數(shù)據(jù)的增刪改查;
雙向綁定

首先我們要理解數(shù)據(jù)綁定。我們看到的網(wǎng)站頁面中,是由數(shù)據(jù)和設(shè)計(jì)兩部分組合而成。將設(shè)計(jì)轉(zhuǎn)換成瀏覽器能理解的語言,便是html和css主要做的工作。而將數(shù)據(jù)顯示在頁面上,并且有一定的交互效果(比如點(diǎn)擊等用戶操作及對(duì)應(yīng)的頁面反應(yīng))則是js主要完成的工作。很多時(shí)候我們不可能每次更新數(shù)據(jù)便刷新頁面(get請求),而是通過向后端請求相關(guān)數(shù)據(jù),并通過無刷新加載的方式進(jìn)行更新頁面(post請求)。那么數(shù)據(jù)進(jìn)行更新后,頁面上相應(yīng)的位置也能自動(dòng)做出對(duì)應(yīng)的修改,便是數(shù)據(jù)綁定。

在以前的開發(fā)模式中,這一步一般通過jq操作DOM結(jié)構(gòu),從而進(jìn)行更新頁面。但這樣帶來的是大量的代碼和大量的操作。如果能在開始的時(shí)候,便已經(jīng)確定好從后端獲取的數(shù)據(jù)到頁面上需要進(jìn)行的操作,當(dāng)數(shù)據(jù)發(fā)生改變,頁面的相關(guān)內(nèi)容也自動(dòng)發(fā)生變化,這樣便能極大地方便前端工程師的開發(fā)。在新的框架中(angualr,react,vue等),通過對(duì)數(shù)據(jù)的監(jiān)視,發(fā)現(xiàn)變化便根據(jù)已經(jīng)寫好的規(guī)則進(jìn)行修改頁面,便實(shí)現(xiàn)了數(shù)據(jù)綁定??梢钥闯觯瑪?shù)據(jù)綁定是M(model,數(shù)據(jù))通過VM(model-view,數(shù)據(jù)與頁面之間的變換規(guī)則)向V(view)的一個(gè)修改。

而雙向綁定則是增加了一條反向的路。在用戶操作頁面(比如在Input中輸入值)的時(shí)候,數(shù)據(jù)能及時(shí)發(fā)生變化,并且根據(jù)數(shù)據(jù)的變化,頁面的另一處也做出對(duì)應(yīng)的修改。有一個(gè)常見的例子就是淘寶中的購物車,在商品數(shù)量發(fā)生變化的時(shí)候,商品價(jià)格也能及時(shí)變化。這樣便實(shí)現(xiàn)了V——M——VM——V的一個(gè)雙向綁定。

這里是區(qū)別于Jquery的,jq操作的是dom對(duì)象,angularJS操作的是變量
依賴注入

對(duì)象在創(chuàng)建時(shí),其依賴的對(duì)象由框架來自動(dòng)創(chuàng)建并注入進(jìn)來??刂破骶褪峭ㄟ^依賴注入的方式實(shí)現(xiàn)對(duì)服務(wù)的調(diào)用。
模塊化設(shè)計(jì)

高內(nèi)聚低耦合法則

高內(nèi)聚:每個(gè)模塊的具體功能具體實(shí)現(xiàn)

低耦合:模塊之間盡可能的少用關(guān)聯(lián)和依賴

1)官方提供的模塊  ng(最核心)、ngRoute(路由)、ngAnimate(動(dòng)畫)

2)用戶自定義的模塊     angular.module('模塊名',[ ])
 
當(dāng)商品庫存數(shù)量不足時(shí),如何保證不會(huì)超賣。

場景一: 如果系統(tǒng)并發(fā)要求不是很高

那么此時(shí)庫存就可以存儲(chǔ)在數(shù)據(jù)庫中,數(shù)據(jù)庫中加鎖串行化減庫存,控制庫存的超賣現(xiàn)象。

場景二:系統(tǒng)的并發(fā)量很大

如果系統(tǒng)并發(fā)量很大,那么就不能再使用數(shù)據(jù)庫來進(jìn)行減庫存操作了,因?yàn)閿?shù)據(jù)庫加鎖操作本身是以損失數(shù)據(jù)庫的性能來進(jìn)行控制數(shù)據(jù)庫數(shù)據(jù)的一致性的。但是當(dāng)并發(fā)量很大的時(shí)候,將會(huì)導(dǎo)致數(shù)據(jù)庫排隊(duì),發(fā)生阻塞。

因此必須使用一個(gè)高效的nosql數(shù)據(jù)庫服務(wù)器來進(jìn)行減庫存,此時(shí)可以使用redis服務(wù)器來存儲(chǔ)庫存,redis是一個(gè)內(nèi)存版的數(shù)據(jù)庫,查詢效率相當(dāng)?shù)母?,可以使用watch來監(jiān)控減庫存的操作,一旦發(fā)現(xiàn)庫存被減為0,立馬停止售賣操作。
商城系統(tǒng)中有以下活動(dòng):

1)      秒殺活動(dòng)

a)    后臺(tái)設(shè)置秒殺商品

b)    設(shè)置秒殺開啟時(shí)間,定時(shí)任務(wù),開啟秒殺

c)    秒殺減庫存(秒殺時(shí)間結(jié)束,庫存賣完,活動(dòng)結(jié)束)

2)      促銷活動(dòng)

3)      團(tuán)購活動(dòng)

4)      今日推薦
涉及到積分積累和兌換商品等業(yè)務(wù)是怎么設(shè)計(jì)的

積分累計(jì)有2大塊:

積分累計(jì):

根據(jù)用戶購買的商品的價(jià)格不同,購買一定價(jià)格的商品,獲取一定的積分。

積分商城:

積分商城是用戶可以使用積分商品換取商品的區(qū)域。
項(xiàng)目的亮點(diǎn)是:

1) 項(xiàng)目采用面向服務(wù)分布式架構(gòu)(使用dubbo,zookeeper)

a)    解耦

b)    提高項(xiàng)目并發(fā)能力

c)    分擔(dān)服務(wù)器壓力

2) 項(xiàng)目中使用activeMQ對(duì)項(xiàng)目進(jìn)一步解耦

a)    提高項(xiàng)目并發(fā)能力

b)    提高任務(wù)處理速度

3)  使用支付寶支付

4)  使用前后端分離

5)  使用第三方分布式文件系統(tǒng)存儲(chǔ)海量文件

6)  Nginx部署靜態(tài)頁面實(shí)現(xiàn)動(dòng)靜分離
購物車流程:

 

秒殺商品流程:

(1)商家提交秒殺商品申請,錄入秒殺商品數(shù)據(jù),主要包括:商品標(biāo)題、原價(jià)、秒殺價(jià)、商品圖片、介紹等信息

(2)運(yùn)營商審核秒殺申請

(3)秒殺頻道首頁列出秒殺商品(進(jìn)行中的)點(diǎn)擊秒殺商品圖片跳轉(zhuǎn)到秒殺商品詳細(xì)頁。將秒殺的商品放入緩存減少數(shù)據(jù)庫瞬間的訪問壓力!

(4)商品詳細(xì)頁顯示秒殺商品信息,點(diǎn)擊立即搶購實(shí)現(xiàn)秒殺下單,下單時(shí)扣減庫存。當(dāng)庫存為0或不在活動(dòng)期范圍內(nèi)時(shí)無法秒殺。讀取商品詳細(xì)信息時(shí)運(yùn)用緩存,當(dāng)用戶點(diǎn)擊搶購時(shí)減少redis中的庫存數(shù)量,當(dāng)庫存數(shù)為0時(shí)或活動(dòng)期結(jié)束時(shí),同步到數(shù)據(jù)庫。

(5)秒殺下單成功,直接跳轉(zhuǎn)到支付頁面(微信掃碼),支付成功,跳轉(zhuǎn)到成功頁,填寫收貨地址、電話、收件人等信息,完成訂單。

(6)當(dāng)用戶秒殺下單5分鐘內(nèi)未支付,取消預(yù)訂單,調(diào)用微信支付的關(guān)閉訂單接口,恢復(fù)庫存。產(chǎn)生的秒殺預(yù)訂單也不會(huì)立刻寫到數(shù)據(jù)庫中,而是先寫到緩存,當(dāng)用戶付款成功后再寫入數(shù)據(jù)庫。
單點(diǎn)登錄怎么做的,知道原理嗎?

在分布式項(xiàng)目中實(shí)現(xiàn)session共享,完成分布式系統(tǒng)單點(diǎn)登錄

Cookie中共享ticket

 Redis存儲(chǔ)session

分布式系統(tǒng)共享用戶身份信息session,必須先獲取ticket票據(jù),然后再根據(jù)票據(jù)信息獲取redis中用戶身份信息。

實(shí)現(xiàn)以上2點(diǎn)即可實(shí)現(xiàn)session共享。目前項(xiàng)目中使用的Shiro+ cas 來實(shí)現(xiàn)的單點(diǎn)登錄,cas自動(dòng)產(chǎn)生ticket票據(jù)信息,每次獲取用戶信息,cas將會(huì)攜帶ticket信息獲取用戶身份信息。

 
介紹一下自己的項(xiàng)目?

我最近的一個(gè)項(xiàng)目是一個(gè)電商項(xiàng)目,我主要負(fù)責(zé)的是后臺(tái)管理和商品詳情的模塊,然后也會(huì)參與到購物車和訂單模塊。這個(gè)項(xiàng)目是以SpringBoot和mybatis為框架,應(yīng)為springBoot相對(duì)于SSM來說 配置方面,還有操作方面簡單很多。然后是采用zookeeper加dubbo分布式架構(gòu)和RPC遠(yuǎn)程調(diào)用,因?yàn)樗鸇ubbo實(shí)現(xiàn)了軟負(fù)載均衡,其特點(diǎn)是成本低,但也會(huì)有缺點(diǎn),就是負(fù)載能力會(huì)受服務(wù)器本身影響,然后為了解決軟負(fù)載均衡的缺點(diǎn),我們使用了Nginx進(jìn)行負(fù)載均衡的輪詢算法,但Nginx主要在我們項(xiàng)目還是實(shí)現(xiàn)反向代理,就是可以防止外網(wǎng)對(duì)內(nèi)網(wǎng)服務(wù)器的惡性攻擊、緩存以減少服務(wù)器的壓力和訪問安全控制?;A(chǔ)模塊就有后臺(tái)管理,商品詳情,訂單,支付,物流情況,庫存服務(wù)。然后SpringBoot整合Thymeleaf模塊技術(shù)開發(fā)項(xiàng)目商品詳情模塊,easyUI開發(fā)后臺(tái)管理項(xiàng)目。至于我負(fù)責(zé)的兩個(gè)模塊呢,就是后臺(tái)管理和商品詳情,其中呢使用了sku和spu的數(shù)據(jù)表結(jié)構(gòu)進(jìn)行增刪改查,spu就好比我們要買一臺(tái)Mate20,但是我們沒有選擇它是什么配置,那么關(guān)于詳細(xì)的配置就是sku了,就是我要買一臺(tái)Mate20,黑色,內(nèi)存是128G的。商品詳情和商品列表模塊使用Nginx實(shí)現(xiàn)集群,使用Redis解決應(yīng)用服務(wù)器的cpu和內(nèi)存壓力,減少io的讀操作,減輕io的壓力,使用分布式鎖防止Redis緩存擊穿。其中Redis的作用我是覺得挺大的,因?yàn)樗梢苑乐惯^多的用戶去直接訪問我們的數(shù)據(jù)庫,當(dāng)然,Redis也會(huì)在高并發(fā)的時(shí)候宕機(jī),在使用Redis做緩存的時(shí)候,我們使用Redis持久化功能,防止Redis宕機(jī)后數(shù)據(jù)丟失,如果Redis宕機(jī)了,用戶就會(huì)大量的去訪問數(shù)據(jù)庫,從而我們數(shù)據(jù)庫也會(huì)崩潰吧。這個(gè)時(shí)候我們就用了一個(gè)分布式鎖,用戶需要獲得一個(gè)鎖才能訪問我們的數(shù)據(jù)庫,當(dāng)然啦,并不只是只有一個(gè)鎖,而是鎖的數(shù)量是有限的,當(dāng)一位用戶查完了數(shù)據(jù)之后,鎖就會(huì)釋放,給下位用戶,這也就是服務(wù)降降級(jí)。沒有獲得鎖的用戶,頁面就一直刷新直到自己拿到鎖為止。redis提供了持久化功能——RDB和AOF。通俗的講就是將內(nèi)存中的數(shù)據(jù)寫入硬盤中。在實(shí)際應(yīng)用中,用戶如果要查詢商品的話呢,首先回到Redis緩存里面找的,如果找不到,就會(huì)到數(shù)據(jù)庫里面找,然后緩存到Redis中,那么下一次或者下一個(gè)用戶需要查找這個(gè)數(shù)據(jù)就不必到數(shù)據(jù)庫中查找了!然后我還參與了購物車和訂單模塊的開發(fā)。購物車模塊里面呢,我先和您講下他的業(yè)務(wù)邏輯吧。就像你逛網(wǎng)頁淘寶一樣,在沒有登錄的時(shí)候,把東西放入購物車,它是不會(huì)和你的賬號(hào)里的商品合并的,這個(gè)時(shí)候,商品就會(huì)以cookie的形式,放到你的瀏覽器里面。這個(gè)時(shí)候如果你想購買這些商品的時(shí)候,你就要登錄,這個(gè)時(shí)候就會(huì)使用到單點(diǎn)登錄這一個(gè)技術(shù)。用戶跳轉(zhuǎn)到訂單頁面的時(shí)候,我們會(huì)用攔截器去進(jìn)行判斷用戶是否已經(jīng)登錄。我們是用cookie中是否有token,如果沒有token的話就跳轉(zhuǎn)到登錄頁面,然后生成token,至于token的生成呢,我們是用本地的IP,用戶的id,保存在map中,還有一個(gè)常量,這個(gè)我們通常會(huì)以項(xiàng)目名稱來命名的。至于為什么要token呢,其實(shí)是因?yàn)閏ookie是不太安全的,它很容易被偽造,所以我們就需要token,然后有了token之后,我們用JWT這個(gè)鹽值生成最后的token。并把它保存到cookie當(dāng)中。下一次支付的時(shí)候我們也還會(huì)用到這個(gè)token,用一個(gè)加密算法再去運(yùn)算驗(yàn)證一下就可以了!然后就是合并購物車了。這個(gè)的話我所知道的就是將客戶端的cookie復(fù)印一份到緩存中進(jìn)行修改然后送回客戶端進(jìn)行覆蓋,再接著就是數(shù)據(jù)庫的修改了。那這個(gè)如果登陸了的就直接從數(shù)據(jù)庫中取得數(shù)據(jù)跳到訂單系統(tǒng)了。然后訂單模塊里面,簡單來說就是從購物車中勾選的商品遷移到訂單里面。但是呢訂單模塊其實(shí)是會(huì)聯(lián)系到另外兩個(gè)模塊的,就是庫存和支付。如果你點(diǎn)擊了提交訂單,商品就會(huì)在購物車?yán)镆瞥?。然后我們提交訂單避免他反?fù)的提交同一個(gè)訂單,就會(huì)通過交易碼防止訂單重復(fù)提交。我們會(huì)吧tradecode放在緩存里面,以用戶id為key商品的交易為value在Redis里面保存這個(gè)交易碼。到最后選好收貨地址,留言之后,提交訂單了,就會(huì)用自己的tradecode和在Redis里面通過用戶的id去獲取tradecode進(jìn)行對(duì)比,如果能跳轉(zhuǎn)到支付頁面,那么緩存中的交易碼就會(huì)刪除掉。到最后就是支付功能,這一步的話我是不太清楚其中的技術(shù)點(diǎn)了,只知道這個(gè)模塊調(diào)用了支付寶的接口和用了消息隊(duì)列,異步通知。