一罢猪、數(shù)據(jù)庫設(shè)計(jì)過于注重范式近她,導(dǎo)致業(yè)務(wù)查詢困難,速度慢膳帕,優(yōu)化難粘捎。
原因:項(xiàng)目剛開始,每個(gè)人都想把公共的邏輯進(jìn)行抽取,在數(shù)據(jù)庫設(shè)計(jì)上追求不冗余晌端。
具象:一個(gè)資源表完整查詢要連4張表,為什么會(huì)有4張恬砂?一張是公共的文件表咧纠,業(yè)務(wù)中所有的文件都存放在這一張表中;一張是資源主表泻骤,負(fù)責(zé)存儲(chǔ)資源業(yè)務(wù)的字段漆羔,兩張是資源表標(biāo)簽表!標(biāo)簽表為什么要兩張狱掂?因?yàn)椴幌胗腥哂鄶?shù)據(jù)演痒。大家很容易接受一個(gè)資源有多個(gè)標(biāo)簽,資源標(biāo)簽表單獨(dú)一張無可厚非趋惨。
惡果:在根據(jù)業(yè)務(wù)建立好索引鸟顺,聯(lián)表查詢4張表的時(shí)候,40W數(shù)據(jù)器虾,沒有用group by(distinct)進(jìn)行去重的時(shí)候是0.03s,一用就變成了9s。主要是在用group by(distinct)的時(shí)候渣锦,出現(xiàn)了萬惡的filesort男韧。
查詢列表時(shí)臨時(shí)性優(yōu)化的策略:因?yàn)橐胓roup by或者distinct進(jìn)行去重,所以根據(jù)查詢條件葛圃,進(jìn)行動(dòng)態(tài)聯(lián)表千扔。查詢結(jié)果返回主鍵ID和結(jié)果總數(shù)。列表需要的字段库正,用ID單獨(dú)查詢后組成返回曲楚。但是一旦要聯(lián)4張表的時(shí)候,優(yōu)化失效褥符,查詢還是很慢洞渤。
后期優(yōu)化方案:1、待業(yè)務(wù)穩(wěn)定后属瓣,將其整合為2張表即可载迄。2、第三方搜索引擎:ES或者sphinx等
二抡蛙、PHP小版本的差異
出現(xiàn)錯(cuò)誤:PDOStatement::execute(): Unknown type 245 sent by the server
原因:MySql用到了json字段护昧,PHP版本無法解析不了MySql數(shù)據(jù)庫的json結(jié)構(gòu),導(dǎo)致查詢一直沒有完成粗截。
出現(xiàn)現(xiàn)象:我本地環(huán)境PHP版本為5.6.16惋耙,程序沒有報(bào)錯(cuò)。開發(fā)環(huán)境上的版本是5.6.14報(bào)錯(cuò)。搜索出來的答案是5.6.13绽榛。
解決方案:讓運(yùn)維把全部環(huán)境的PHP版本給升級(jí)了湿酸。(希望不要被運(yùn)維的同學(xué)拿刀砍)
結(jié)論:環(huán)境的統(tǒng)一真的很重要,哪怕是差別兩個(gè)最小版本的PHP也會(huì)出現(xiàn)問題灭美,對(duì)環(huán)境不相同推溃,必然會(huì)發(fā)生因?yàn)榄h(huán)境的差異的錯(cuò)誤。
三届腐、對(duì)程序語言細(xì)節(jié)的特性的忽視
現(xiàn)象1:var_dump("kkk"===0);
會(huì)輸出 bool(true);當(dāng)PHP字符串與數(shù)字進(jìn)行比較的時(shí)候铁坎,若字符串中首位有數(shù)字,則用首位數(shù)字與數(shù)字進(jìn)行比較犁苏,否則將字符串將轉(zhuǎn)為0硬萍。
現(xiàn)象2:php用curl 傳遞參數(shù),多維數(shù)組要用用http_build_query围详,但是build后朴乖,發(fā)現(xiàn)傳遞是整形的數(shù)字變成了string類型。
示例:$post_data = http_build_query(["key" => ['integer' => 10]]); ?接收后json化輸出:{"key":{"integer":"10"}}
對(duì)于PHP這點(diǎn)助赞,如果要嚴(yán)格字段類型寒砖,只能通過事先約定進(jìn)行避免。雖然phper的我們不會(huì)太在意這點(diǎn)細(xì)小的差異嫉拐。但是有時(shí)對(duì)于我接收方要求嚴(yán)謹(jǐn)類型的時(shí)候哩都,這就成了我們的災(zāi)難
現(xiàn)象3:有兩個(gè)類分別為A、B婉徘。在A中有個(gè)方法實(shí)例化了B漠嵌,在調(diào)用B中方法時(shí),無法再實(shí)例化A盖呼。
現(xiàn)象4:PHP無法通過http訪問本地IP共享的文件夾儒鹿,卻可以通過CLI的形式去訪問
這個(gè)問題找了挺久,實(shí)在是找不到原因几晤。而且通過CLI已經(jīng)實(shí)現(xiàn)了功能约炎,工作上并沒有更多時(shí)間讓人去深究這樣的原因。
現(xiàn)象5:c++在客戶端傳空格給php蟹瘾,要將空格轉(zhuǎn)換成+號(hào)圾浅,PHP無法識(shí)別
原因:
意外收獲:這個(gè)我是剛在搜索http_build_query函數(shù)時(shí),發(fā)現(xiàn)的憾朴。之前我也不清楚是什么原因狸捕。
現(xiàn)象6:c++開發(fā)問題,請(qǐng)求PHP接口众雷,搜索時(shí)傳遞三個(gè)漢字無法返回結(jié)果
原因:由于兩個(gè)漢字為3字節(jié)一個(gè) 加上一個(gè)空 為奇數(shù)灸拍,轉(zhuǎn)碼時(shí)可以找到尾部做祝,3個(gè)是為偶數(shù),找不到尾部鸡岗,故而PHP無法解析混槐。
現(xiàn)象7:用Python腳本上傳文件到OSS時(shí),出現(xiàn)文件為空的現(xiàn)象
原因:python 用 file open a轩性,當(dāng)a.read()只能讀一次声登,再讀第二次為null。我們想象中的是多次讀是一樣有內(nèi)容的炮姨。
惡果的解決方案:把OSS上的文件遍歷一遍捌刮,發(fā)現(xiàn)空的碰煌,重新上傳吧舒岸。
四、慣性思維的盲區(qū)
現(xiàn)象:開發(fā)時(shí)是只用一個(gè)賬號(hào)進(jìn)行調(diào)試芦圾,或者只按照自己設(shè)計(jì)的程序思路去調(diào)試
后果:自己跑的時(shí)候完全沒有問題蛾派,一到其他人手上就出現(xiàn)了問題(bug)
對(duì)于這個(gè)問題,是不能有明確的界限定義的个少。因?yàn)槌绦蚣词故峭ㄟ^了測(cè)試洪乍,上線后的程序也會(huì)出現(xiàn)bug。誰也不能保證沒有bug的程序出現(xiàn)夜焦。
舉個(gè)例子:我在Yii里面用了seaslog插件壳澳,默認(rèn)的路徑是按照“模塊/控制器/方法”的規(guī)則去設(shè)置的,而Yii無論是跑http請(qǐng)求還是跑cli請(qǐng)求都會(huì)有經(jīng)過模塊-控制器-方法茫经,但是單元測(cè)試的時(shí)候巷波,就不會(huì)有這些,所以程序必然報(bào)錯(cuò)卸伞。
其實(shí)我們?cè)谠O(shè)計(jì)程序的時(shí)候抹镊,是基于需求下進(jìn)行設(shè)計(jì)的,而對(duì)于需求之外(邊界之外)的情況荤傲,我們的程序就要給出合理的回應(yīng)垮耳,而異常是我們慣用的手段。
在我舉的這個(gè)例子中遂黍,如果我不寫單元測(cè)試终佛,可能我永遠(yuǎn)都不會(huì)發(fā)現(xiàn)自己的程序有漏洞。所以有些bug雾家,只是潛伏在你的代碼里面查蓉,但一旦爆發(fā)就會(huì)是災(zāi)難性的。如果要避免自己少慣性思維的錯(cuò)誤榜贴,還是對(duì)自己的程序?qū)Χ鄿y(cè)試豌研,或者進(jìn)行的code review妹田。
五、多人協(xié)助鹃共,缺乏架構(gòu)和統(tǒng)一的指導(dǎo)
現(xiàn)象:我們目前是開發(fā)一個(gè)平臺(tái)鬼佣,平臺(tái)中有許多應(yīng)用。一個(gè)開發(fā)者可以要開發(fā)幾個(gè)應(yīng)用霜浴,而多個(gè)開發(fā)者共同維護(hù)一份代碼
目前暴露的問題:
1晶衷、應(yīng)用之間的耦合度高,許多應(yīng)用無法進(jìn)行單獨(dú)部署阴孟。直接導(dǎo)致公司在做銷售策略上無法靈活應(yīng)變晌纫。因?yàn)槲覀冎荒茏隼変N售,必然導(dǎo)致客戶的成本提高永丝。試問哪個(gè)客戶會(huì)是傻子锹漱?
2、代碼重復(fù)慕嚷,應(yīng)用間存在業(yè)務(wù)性的重復(fù)哥牍,但是在代碼上沒有人將其進(jìn)行整合。重復(fù)工作是必然的喝检。一方面嗅辣,無形間是增加了公司的開發(fā)成本。另一方面是各個(gè)開發(fā)者無法感知其他其他開發(fā)者做的事挠说,即是無法站在全局高度上去思考的問題澡谭,:最終限制了開發(fā)者自身的發(fā)展。
目前解決方案:目前我們的技術(shù)經(jīng)理擔(dān)當(dāng)起了統(tǒng)領(lǐng)全局的職責(zé)损俭。將平臺(tái)的公共模塊專職交由一個(gè)人進(jìn)行負(fù)責(zé)蛙奖,讓一個(gè)人將各個(gè)應(yīng)用的開發(fā)者進(jìn)行聯(lián)系起來×么叮“代碼集體所有外永,個(gè)人負(fù)責(zé)到應(yīng)用”,這是技術(shù)經(jīng)理的提倡的思想拧咳。
六伯顶、總想搞事情,但是總搞不好B嫦ァ<礼谩!
現(xiàn)象1:在10月份的時(shí)候阅签,平臺(tái)會(huì)出一個(gè)重大的功能版本掐暮,作為一個(gè)里程牌。但是在開發(fā)重大功能的同時(shí)政钟,前端對(duì)其架構(gòu)進(jìn)行根本性的調(diào)整路克。導(dǎo)致平臺(tái)的新功能延期了一個(gè)多月才能進(jìn)行交付樟结。
原因:而前端對(duì)其架構(gòu)做了根本性的調(diào)整的時(shí)候,并沒有做好全面性的測(cè)試精算,再者根本沒有人去評(píng)估風(fēng)險(xiǎn)瓢宦。即是除了前端的負(fù)責(zé)人,跟他關(guān)聯(lián)的人壓根沒有收到任何評(píng)估的通知灰羽,只能被動(dòng)的配合驮履。
在我看來,一次迭代只做一件事廉嚼,永遠(yuǎn)比一大堆功能扎堆上線要穩(wěn)妥玫镐。同時(shí),作為一個(gè)項(xiàng)目的負(fù)責(zé)人怠噪,更加要兼顧全局恐似,不能自嗨!
現(xiàn)象2:在7舰绘、8月前蹂喻,我們規(guī)劃出了一個(gè)支撐平臺(tái)葱椭。目的是:1捂寿、作為業(yè)務(wù)應(yīng)用的數(shù)據(jù)來源;2孵运、將業(yè)務(wù)應(yīng)用的公共功能進(jìn)行抽取為公共服務(wù)秦陋,轉(zhuǎn)由支撐平臺(tái)提供。進(jìn)而實(shí)現(xiàn)快速生產(chǎn)業(yè)務(wù)應(yīng)用的效果治笨。但是直到現(xiàn)在支撐平臺(tái)還沒有能全面的落實(shí)驳概。
原因:開發(fā)支撐平臺(tái)的人,想做的事情太多了旷赖。按照公司現(xiàn)階段的業(yè)務(wù)顺又,支撐平臺(tái)就是做一個(gè)Auth驗(yàn)證和一個(gè)路由器的功能即可,其實(shí)就是一個(gè)企業(yè)服務(wù)總線(ESB)等孵,因?yàn)楣疽呀?jīng)存在提供數(shù)據(jù)來源的應(yīng)用和一些公共服務(wù)稚照。至于負(fù)載均衡、日志和統(tǒng)計(jì)分析的事情俯萌,可以設(shè)計(jì)留白果录,往后慢慢再實(shí)現(xiàn)。
我的觀點(diǎn)是咐熙,從小變大弱恒,做好框架,隨時(shí)應(yīng)變棋恼。
小結(jié)
坑返弹,總是令人成長(zhǎng)的锈玉,多么痛的領(lǐng)悟。但是义起,無論是做什么嘲玫,生存下來才是硬道理!