App架構經驗總結

原文地址:http://www.iteye.com/news/31472
-------------------------------------------------------------
架構因人而異,不同的架構師大多會有不同的看法;架構也因項目而異,不同的項目需求不同,相應的架構也會不同。然而,有些東西還是通用的,是所有架構師都需要考慮的,也是所有項目都會有的需求,比如API如何設計?架構如何分層?開發環境和生產環境如何分離?這幾年,我負責研發過的App,有餐飲類的、社交類的、智能家居類的、電商類的、新聞媒體類的等等。當有了一定的經驗之后,你總會有一些自己的心得體會。而以下內容就是根據我的這些經歷提煉出來的關于以上幾個問題方面的經驗總結,內容不多,旨在拋磚引玉。?

從API開始?

一個App,最核心的東西,其實就是數據,而數據的主要來源,就是API。我之前負責的項目,因為API的坑已經受過了不少苦,因此,之后對App項目的架構設計我都會先從API開始。?

制定安全機制?

設計API第一個需要考慮的是API的安全機制。我負責的上一個項目,因為API的安全問題,就被人攻擊了兩次。之后經過分析,主要存在兩個漏洞:一是因為缺少對調用者進行安全驗證的方式,二是因為數據傳輸不夠安全。那么,制定API的安全機制,主要就是為了解決這兩個問題:?
  • 保證API的調用者是經過自己授權的App;
  • 保證數據傳輸的安全。

第一個問題的解決方案,我主要采用設計簽名的方式。對每個客戶端,Android、iOS、WeChat,分別分配一個AppKey和AppSecret。需要調用API時,將AppKey加入請求參數列表,并將AppSecret和所有參數一起,根據某種簽名算法生成一個簽名字符串,然后調用API時把該簽名字符串也一起帶上。服務端收到請求之后,根據請求中的AppKey查詢相應的AppSecret,按照同樣的簽名算法,也生成一個簽名字符串,當服務端生成的簽名和請求帶過來的簽名一致的時候,那就表示這個請求的調用者是經過自己授權的,證明這個請求是安全的。而且,每個端都有一個Key,也方便不同端的標識和統計。為了防止AppSecret被別人獲取,這個AppSecret一般寫死在代碼里面。另外,簽名算法也需要有一定的復雜度,不能輕易被別人破解,最好是采用自己規定的一套簽名算法,而不是采用外部公開的簽名算法。另外,在參數列表中再加入一個時間戳,還可以防止部分重放攻擊。?

第二個問題的解決方案,主要就是采用HTTPS了。HTTPS因為添加了SSL安全協議,自動對請求數據進行了壓縮加密,在一定程序可以防止監聽、防止劫持、防止重發,主要就是防止中間人攻擊。蘋果從iOS9開始,默認就采用HTTPS了。而關于在Android中如何使用HTTPS,Google官方也給出了很多安全建議。不過,大部分App并沒有按照安全建議去實現,主要就是沒有對SSL證書進行安全性檢查,這就成為了一個很大的漏洞,中間人利用此漏洞用假證書就可以通過檢查,從而可以劫持到所有數據了。因此,為了安全考慮,建議對SSL證書進行強校驗,包括簽名CA是否合法、域名是否匹配、是不是自簽名證書、證書是否過期等。?

接口協議標準化?

API返回的數據,一般都是采用JSON格式進行傳輸。然而,JSON的值只有六種數據類型:?
  • Number:整數或浮點數
  • String:字符串
  • Boolean:true 或 false
  • Array:數組包含在方括號[]中
  • Object:對象包含在大括號{}中
  • Null:空類型

我遇到過的,關于API的坑有大部分就是因為JSON數據和實體對象轉化時出錯導致的,而且是各種各樣的錯誤都有,其中不乏有一些很奇葩的錯誤。?

最麻煩的就是處理Date類型,因為JSON本身沒有Date類型,因此,JSON庫將Date類型的數據序列化時會轉為String。這時,不同環境,不同平臺,以及用不同的JSON解析庫,轉換后的結果經常會不同。比如,你在開發機上可能得到的結果是”2016-1-1 17:11:11”,但放到服務器后結果卻變成了“Jan 1,2016 5:11:11 PM” ,客戶端進行反序列化時無疑會失敗。后來,我取消了所有Date類型,統一采用時間戳表示,就再沒有轉化的煩惱了。?

另外,接口的開發人員有時候會將一些數據錯誤地轉換為了String,導致客戶端使用時因類型錯誤而異常。例如,本來是數字的1,被轉成了"1",客戶端做運算時就會出錯,或用switch判斷時也會出錯,或其他無法轉換的情況發生時;例如,為空時JSON正確地表示應該是null,但如果轉為了String就變成了"null",那問題就來了,我遇到的因為這個錯誤的轉換導致的程序奔潰已經好幾次了,第一次的時候,查了一整天才定位到問題所在。?

還有,因為接口的開發人員不同,很多時候還會出現不同接口同一個意思的參數名稱卻不同。比如,對于有分頁數據的接口,一般都有當前頁的參數,A開發人員可能將參數命名為currentPage,第一頁是從0開始;B開發人員在另一個接口則命名為currPage,第一頁卻從1開始;C開發人員在另一個接口又命名為presentPage,第一頁又是從0開始。客戶端的開發人員看到也是醉了。?

每個技術團隊一般都會有一份接口協議文檔,主要內容包括每個接口的描述、入參、輸出結果等,但一般并不嚴謹,很多地方沒有統一標準,從而容易出現很多坑。因此,有一份統一標準且嚴格執行的接口協議非常重要。協議的內容除了規定每個接口,包括接口中每個數據具體的數據類型,還需要規定一套共用的數據字典,以及其他需要統一定義的信息,比如簽名算法等。一旦有了這份統一標準且嚴格執行的接口協議,很多問題都將迎刃而解。?

接口版本控制?

我們已經不止一次因為接口發生變動而導致舊版本的App出錯的問題,而且變動不一定是修改了接口本身,有可能是底層增加了一種新的數據結構,接口把新數據也返回給客戶端了,但客戶端舊版本是解析不了的,從而就導致出錯了。?

為了解決接口的兼容性問題,需要做好接口版本控制。實現上,一般有兩種做法:?
每個接口有各自的版本,一般為接口添加個version的參數;?
整個接口系統有統一的版本,一般在URL中添加版本號,比如http://api.domain.com/v2。?
平時小版本的更新,就采用第一種方式,我們的做法是根據不同版本號做不同分支處理。大版本的更新,則用第二種方式,這時候,基本就是一套全新的接口系統了,跟舊版本是相對獨立的。?

當版本越來越多時,維護就會成為一個大問題,我們沒那么多精力去維護所有版本,因此,太舊的版本一般就不會再維護了。這時候,如果有用戶還在使用即將廢棄的舊版本,需要提醒用戶升級到新版本。?

架構分層?

API的設計完成之后,接下來我就會考慮App項目的整體架構了。整體如何架構,我也曾經做過不少嘗試。早期的時候,Android就是將所有操作都放在Activity里完成,包括界面數據處理、業務邏輯處理、調用API。后來發現Activity越來越臃腫,代碼越來越復雜,很難維護。于是就開始思考如何拆分,如何才能做到松耦合高內聚。?

前面也說過,一個App的核心就是數據,那么,從App對數據處理的角色劃分出發,最簡單的劃分就是:數據管理、數據加工、數據展示。相應的也就有了三層架構:數據層、業務層、展示層。它們之間的關系如下圖,數據層是三層中的最底層,往下,它接入API;往上,它向業務層交付數據。業務層夾在三層中間,屬于數據的加工廠,將數據層提供上來的數據加工成展示層需要展示的數據。展示層處于三層中的最上層,主要就是將從業務層取得的數據展示到界面上。?

?

數據層?

數據層是數據管理者,主要任務就是封裝API,并將數據結果交付給上層,中間會再加個數據緩存。整個主流程如下圖:?

?

  • 業務層向數據層請求數據;
  • 數據層檢查緩存中有沒有請求需要的數據;
  • 如果有緩存數據,則直接返回緩存數據;
  • 如果沒有緩存數據,則從網絡API獲取數據,并將數據加入緩存,然后返回數據。

調用網絡API時,還要判斷網絡狀態,根據不同狀態做不同處理。如果網絡不可用,就無需發起請求了。網絡可用時,也要區分是連接WIFI還是連接移動網絡。連接移動網絡時,一般需要限制調用比較耗流量的請求。曾經,我們沒有對移動網絡狀態下的請求進行限制,結果,測試時流量DuangDuangDuang地一下子就不見了十幾M。連接WIFI時,則無需設置這種限制,而且還可以預先請求一些接口,比如請求當前分頁數據時,可以將下一頁的數據也預先請求。?

緩存也需要緩存策略,不同的接口需要做不同的緩存處理。首先,緩存只適用于獲取數據的接口,對于修改數據的接口則不適用。其次,不同接口緩存時間一般也不同,對于很少變動的數據緩存時間可以設置長一些,而頻繁變動的數據緩存時間則比較短,甚至不進行緩存。最后,緩存數據因為比較多,我們一般保存在數據庫,而對于調用頻率高、最新的數據,還會在內存中也擁有一份緩存,不過緩存時間比較短。請求緩存數據時,會先檢查內存緩存中有沒有,有則直接將緩存的數據返回,沒有才從數據庫獲取。?

那么,如何將數據交付給業務層呢?這是整個數據層模塊與外部交互的部分,當與外部交互的時候,一般都要符合面向接口編程的原則,因此只要提供開放的數據接口就可以了。對于接口的參數需要說明一下,上面提到的參數有appKey、version、currentPage這幾個,還有簽名sign、時間戳time,其實可以分為兩類:系統參數和業務參數。像appKey、version、sign、time這些屬于系統參數,而currentPage,或username之類的則屬于業務參數。數據層開放的數據接口的參數只需要包含業務參數就可以了,業務層并不需要關心系統參數是什么,系統參數在數據層內部封裝API時指定就可以了。?

業務層?

業務層是數據加工者,主要就是從數據層獲取數據,然后經過業務邏輯處理后轉化成展示層需要的數據。業務層因為夾在數據層和展示層中間,起著承上啟下的作用。也因此,業務層很容易淪落為只是一個數據的中轉站,主要就是因為對業務層具體的作用和職責沒有理解清楚。?

這里用一個例子來說明業務層具體的工作吧,就舉個用戶注冊的例子。用戶注冊時,界面上需要用戶提供手機號、短信驗證碼、密碼、確認密碼。那么,最簡單的操作就是,帶上這些參數調用數據層的注冊接口。好了,問題來了,注冊接口并沒有提供確認密碼的參數。那好,調用注冊接口之前先判斷下密碼和確認密碼是否一致,不一致則返回錯誤提示給用戶,一致了才調用注冊接口。好了,第二個問題來了,用戶等網絡請求等了一段時間后,請求結果返回說手機號少了一位。下一次,又等了一段時間,這次又返回說手機號多了一位。就因為一個小錯誤要讓用戶等那么久,用戶肯定有意見。后臺也有意見,各種非法的請求都發過來,是嫌服務器壓力不夠大啊。那好,調用接口之前對這些參數做有效性檢查吧,手機號要規范,短信驗證碼只能為六位數字,密碼不能少于六位。終于注冊成功了,第三個問題又來了,注冊接口是沒有返回用戶的accessToken的,只有登錄接口才會返回。讓用戶手動再登錄一下?這用戶體驗不太好啊。正確的姿勢應該是注冊成功后再自動調用一次登錄接口,如果因為網絡問題第一次登錄失敗,后面還需要再自動調用多一次,如果還是調用失敗,才讓用戶手動登錄。?

上面的例子中,對參數的有效性檢查,注冊成功后的自動登錄,都屬于業務邏輯的處理,也就是說都是業務層的工作。?

業務層交付給展示層的數據也是通過接口的方式,不過,和數據層交付給業務層時不同的是:交付給展示層的數據應該是通過異步回調返回的。因為獲取數據是一個比較耗時的任務,通過異步回調才不會阻塞UI主線程。?

展示層?

展示層作為數據展示者,它只要關心數據如何展示就可以了。不過,數據如何展示卻不是那么簡單。展示層是三層架構中最復雜的一層了,要考慮的東西遠遠多于其他兩層,涉及的東西包括但不限于界面布局、屏幕適配、圖片資源、文本資源、顏色資源等等。在開發一段時間后,展示層出現代碼混亂是最常見的。因此,做好展示層,就需要保持高質量的代碼。要保持高質量代碼,我覺得至少應該遵循幾條基本的原則:?
  • 保持規范性:定義好開發規范,包括書寫規范、命名規范、注釋規范等,并按照規范嚴格執行;
  • 保持單一性:布局就只做布局,內容就只做內容,各自分離好,每個方法、每個類,也只做一件事情;
  • 保持簡潔性:保持代碼和結構的簡潔,每個方法,每個類,每個包,每個文件,都不要塞太多代碼或資源,感覺多了就應該拆分。

所謂無規矩不成方圓,展示層的設計,要從開發規范開始。一份好的開發規范,是保證代碼有較高的可讀性的基礎。iOS方面,蘋果已經有一套Coding Guidelines,主要屬于命名方面的規范。當我們制定自己的開發規范時,首先就要遵守蘋果的這份規范,在此基礎上再加上自己的規范。Android方面,我也在我的博客中分享過一套(Android技術積累:開發規范),主要分為書寫規范、命名規范、注釋規范三部分。?

最重要的不是開發規范的制定,而是開發規范的執行。如果沒有按照開發規范去執行,那開發規范就等于形同虛設,那代碼混亂的問題依然得不到解決。?

說到單一性,面向對象設計中,有一個基本原則就是單一職責原則,它規定一個類應該只有一個發生變化的原因。保持單一性是減低耦合度的關鍵標準,其目的就是各方面的解耦。而我這里說的單一性不只是規定類的單一,也包括界面的單一、方法的單一、資源文件的單一等。?

界面的單一,首先是界面的布局和界面的數據應該分離。另外,界面數據的獲取和展示也應該分離。一句話,保持界面的單一性就是要保持界面上每個維度都做好分離,從界面的布局,到數據的獲取,數據的檢查,數據的展示。?

方法的單一,則表現為一個方法是對一個行為的封裝。行為又可以拆分為多個步驟,每個步驟其實也是更細化的行為。因此,方法嵌套方法是一種常態。那么,保持方法的單一性,關鍵不在于怎么定義這個方法的行為,而在于這個行為要怎么拆分成更細的行為。舉個例子,通常在Activity的onCreate方法,做初始化操作,細分出來就分為了:控件的初始化、邏輯變量的初始化、數據的初始化。數據的初始化又可以再細分:數據的獲取、數據的展示。每個細化的行為都應該封裝為一個獨立的方法,這樣,才真正符合方法的單一性。?

資源文件的單一,主要是指Android的各類資源文件,包括存放字符串的strings.xml,存放字符串數組的arrays.xml,存放顏色值的colors.xml,存放尺寸值的dimens.xml,等等。資源文件的單一,是說所有相關的資源信息要在資源文件里定義并引用到代碼或布局文件里,而不是在代碼或布局文件里直接定義。這樣做,可以很方便地做各種適配和修改,比如支持國際化,比如不同分辨率的屏幕用不同尺寸值。iOS則沒有提供和Android一樣的資源文件分離的機制,但可以參考Android的做法自己去實現。?

環境分離?

每個App項目,至少都會有兩個環境:測試環境和生產環境。多的甚至有四個環境:開發環境、測試環境、預生產環境和生產環境。開發人員經常需要在環境之間切換,測試人員也同樣。經常出現測試人員今天需要測試環境的最新版本,叫App開發人員打包一個給她,明天需要切換到生產版本,再叫App開發人員打包一個生產環境的給她。我們知道,一個App,在一臺手機上要么只能是測試環境的,要么只能是生產環境的。測試人員要測試兩個環境,只能不斷替換不同環境的同個App,這實在太麻煩了。為了解決此問題,最好的方案就是環境分離,不同環境有不同的App。?

一個App的唯一標識,Android是用包名,iOS是用Bundle Identify。那么,在一個系統想安裝不同環境的App,只要每個環境App的包名和Bundle Identify不同即可。比如,生產版的包名和Bundle Identify命名為com.mydomain.myapp,測試版的包名和Bundle Identify則命名為com.mydomain.myapp.beta,這樣,Android和iOS都會識別為兩個不同的App了。?

不過,只改包名和Bundle Identify是不夠的,應用圖標和應用名稱也要修改,不然安裝之后很難區分哪個App是哪個環境的。一般做法就是,非生產環境的App圖標就是在生產圖標的基礎上添加一個環境標簽,同時App的應用名稱也是在生產的基礎上添加環境后綴名。另外,因為包名和Bundle Identify不同了,微信、微博、百度地圖等這些第三方平臺也都需要為不同環境的App分別申請不同的appID。?

實現上,最笨的方法就是拷貝當前工程,然后修改,缺陷很明顯,維護成本很高。不過,好在Android和iOS都有很方便的修改方式。?

Android有了Gradle,可以設置多個不同的Flavors,每個Flavor都有一個applicationId屬性,其實就是App的包名。比如,生產版和測試版的設置如下:?
Java代碼?
  1. productFlavors?{??
  2. ????myapp?{??
  3. ????????applicationId?"com.mydomain.myapp"??
  4. ????}??
  5. ????myappBeta?{??
  6. ????????applicationId?'com.mydomain.myapp.beta'??
  7. ????}??
  8. }??

這樣,其實就有兩個App了。然后,源代碼新建一個和main同級的目錄,命名為myappBeta,然后,將圖標、名稱和第三方設置之類的,和main保持一樣的位置、文件名、屬性等,就可以替換成環境相關的了。?

iOS則可以通過創建多個環境的Target來實現環境分離,不同Target可以設置不同的Bundle Identify、Bundle display name、更換圖標。另外,每個Target也各自有自己的一份plist文件的,環境變量和第三方設置之類的,都可以設置在相應的plist文件里。?

寫在最后?

至此,關于App架構方面的經驗總結就先講這么多了。其中,部分內容在我以往的博客上也已經有所體現,有興趣的讀者可以前往我的博客了解并歡迎參與討論。?

本文刊載在《程序員》雜志2016年3期,版權歸《程序員》所有,未經許可不得轉載
  • 查看圖片附件
4?
1?
評論?共 4 條 請登錄后發表評論
4 樓?hongsen.liu?2016-04-05 09:27
恩,作者總結的非常好,學習了
3 樓?冰糖葫蘆?2016-04-01 23:18
yeak2001 寫道
為什么要把關鍵的算法都寫在客戶端?客戶端里接受到的應該是加密過的appSecrect,傳輸到服務端然后解密匹配。

冰糖葫蘆 寫道
請問原作者還在么,我這關于API的安全機制有問題想請教下:
1. 關于安全機制第二條:安全傳輸使用Https我統一,但對于一般團隊來說,https帶來的成本開銷還是挺大的。
2.關于第一條中對“調用者身份”的驗證,這條我們同樣采用了改機制:
?? a.根據appSecrect以及一些其他參數生成sign
?? b.在接口中加入了timestamp來做過期校驗防止同樣參數一直請求
?? c.將業務參數按一定規則排序后生成data_sign(防止業務參數被篡改)
但是我們還是被攻擊了,為啥?因為我們還有一個移動版頁面,而該移動頁面使用angularjs實現,那么所有的關鍵參數、算法都就被暴露在js中了,這正是被攻擊原因。
請問作者在這方面有啥建議么,求交流!!!



這個說法我不太贊同,appSecret在這里的作用跟密鑰作用類似,試問密鑰怎么能傳輸的,我認為應該傳輸的是appkey,而服務端用appkey來找到其secret并根據算法生成摘要來校驗客戶端傳過來的簽名參數(簽名是客戶端根據其appsecret生成,因此客戶端應對其妥善保管)
2 樓?yeak2001?2016-04-01 01:38
為什么要把關鍵的算法都寫在客戶端?客戶端里接受到的應該是加密過的appSecrect,傳輸到服務端然后解密匹配。

冰糖葫蘆 寫道
請問原作者還在么,我這關于API的安全機制有問題想請教下:
1. 關于安全機制第二條:安全傳輸使用Https我統一,但對于一般團隊來說,https帶來的成本開銷還是挺大的。
2.關于第一條中對“調用者身份”的驗證,這條我們同樣采用了改機制:
?? a.根據appSecrect以及一些其他參數生成sign
?? b.在接口中加入了timestamp來做過期校驗防止同樣參數一直請求
?? c.將業務參數按一定規則排序后生成data_sign(防止業務參數被篡改)
但是我們還是被攻擊了,為啥?因為我們還有一個移動版頁面,而該移動頁面使用angularjs實現,那么所有的關鍵參數、算法都就被暴露在js中了,這正是被攻擊原因。
請問作者在這方面有啥建議么,求交流!!!

1 樓?冰糖葫蘆?2016-03-30 22:37
請問原作者還在么,我這關于API的安全機制有問題想請教下:
1. 關于安全機制第二條:安全傳輸使用Https我統一,但對于一般團隊來說,https帶來的成本開銷還是挺大的。
2.關于第一條中對“調用者身份”的驗證,這條我們同樣采用了改機制:
?? a.根據appSecrect以及一些其他參數生成sign
?? b.在接口中加入了timestamp來做過期校驗防止同樣參數一直請求
?? c.將業務參數按一定規則排序后生成data_sign(防止業務參數被篡改)
但是我們還是被攻擊了,為啥?因為我們還有一個移動版頁面,而該移動頁面使用angularjs實現,那么所有的關鍵參數、算法都就被暴露在js中了,這正是被攻擊原因。
請問作者在這方面有啥建議么,求交流!!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/539682.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/539682.shtml
英文地址,請注明出處:http://en.pswp.cn/news/539682.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python數字排序 循環_【python-leetcode448-循環排序】找到所有數組中消失的數字

問題描述:給定一個范圍在 1 ≤ a[i] ≤ n ( n 數組大小 ) 的 整型數組,數組中的元素一些出現了兩次,另一些只出現一次。找到所有在 [1, n] 范圍之間沒有出現在數組中的數字。您能在不使用額外空間且時間復雜度為O(n)的情況下完成這個任務嗎…

saiku+kettle整合(六)olap操作

title: saikukettle整合(六)olap操作 tags: categories: saiku date: 2016-08-25 18:18:54 使用saiku可以對應使用相關olap操作 OLAP的基本操作 我們已經知道OLAP的操作是以查詢——也就是數據庫的SELECT操作為主,但是查詢可以很復雜&#xf…

攜程Docker實踐

原文地址:http://www.iteye.com/news/31468 請點擊原文閱讀 ---------------------以下是原文---------------------- 從去年底開始,攜程開始計劃把Docker引入到攜程的云平臺,這是系統研發部一部分的工作任務,攜程系統研…

mysql全文索引thinkphp_ThinkPHP5 使用迅搜 (XunSearch) 實現全文檢索實例指導

前期準備入坑了一天,折騰的無語,個人觀點:【文檔太差,適合學習思路,不建議入坑】背景最近在整理全文檢索解決方案注意到 xunsearch 的評價很高,在此記錄一番場景描述此處作為對 xunsearch 的初次使用&#…

為何有些程序員總是想要“干掉”產品經理?

好了,我準備去和產品經理做斗爭去了,請祝我好運吧!小編花了大量時間收集了很多干貨編程學習資源,其中資源包括 算法,大數據,人工智能,Python,Android,iOS,Jav…

多個left join 產生多個結果

select a.*,to_char(To_date(20160403000000, yyyyMMddhh24miss),yyyy/mm/dd) as omc_start_time,to_char(To_date(20160404000000, yyyyMMddhh24miss),yyyy/mm/dd) as omc_end_time,ROUND(sc."切換成功率",2) AS "OMC-源小區切換成功率%",ROUND(sc."…

查看進程占用,并kill掉

今天發現8899端口被占,服務器啟動失敗,用了下面的命令解決。 [rootltesqm Toolbox]# netstat -tunlp |grep 8899 tcp 0 0 :::8899 :::* LISTEN 28279/java [rootltesqm Toolbox]…

Spark算子篇 --Spark算子之combineByKey詳解

一。概念 rdd.combineByKey(lambda x:"%d_" %x, lambda a,b:"%s%s" %(a,b), lambda a,b:"%s$%s" %(a,b))三個參數(都是函數)第一個參數:給定一個初始值,用函數生成初始值。第二個參數:c…

mysql proxy 主從_【MYSQL知識必知必會】MySQL主從復制讀寫分離(基于mysql-proxy實現)...

MySQL主從復制讀寫分離(基于mysql-proxy實現)http://mirror.bit.edu.cn/mysql/Downloads/MySQL-Proxy/mysql-proxy-0.8.4-linux-glibc2.3-x86-64bit.tar.gz解壓tar zxvf mysql-proxy-0.8.4-linux-glibc2.3-x86-64bit.tar.gz創建mysql-proxy帳號并授權分別在主從數據庫中創建mys…

SecureCRT防止自動斷開

今天在寧波連接上海的linux庫,是外網訪問內網,使用了nat123這個軟件映射的。 發現SecureCRT連接后,過幾分鐘就自動斷開,導致使用SecureCRT做跳轉機的其他應用使用起來很不方便。 于是設置了下SecureCRT。

mysql 主主結構_高性能mysql主主架構

(3)配置參數說明server-id:ID值唯一的標識了復制群集中的主從服務器,因此它們必須各不相同。master_id必須為1到232–1之間的一個正整數值,slave_id值必須為2到232–1之間的一個正整數值。log-bin:表示打開binlog,打開該選項才可以…

解決ios編譯swift報錯pcm was built: mtime changed

問題 編譯ios工程失敗時,其中的幾個swift文件報以下錯 /Users/tomes/code/project/xxx.swift File /Users/tomes/Library/Developer/Xcode/DerivedData/Spec-dgyhrnmgvfkjkqbboklnfgrudqip/Build/Products/Debug-iphoneos/xxxx.framework/Headers/xxxx.h has been…

AI工程師職業規劃和學習路線完整版

AI工程師職業規劃和學習路線完整版 如何成為一名機器學習算法工程師 成為一名合格的開發工程師不是一件簡單的事情,需要掌握從開發到調試到優化等一系列能 力,這些能力中的每一項掌握起來都需要足夠的努力和經驗。而要成為一名合格的機器學習算法工程師&…

oracle 多個with as

主要看多個with的格式 [sql] view plaincopy WITH T3 AS ( SELECT T1.ID, T1.CODE1, T2.DESCRIPTION FROM TB_DATA T1, TB_CODE T2 WHERE T1.CODE1 T2.CODE ), T4 AS ( SELECT T1.ID, T1.CODE2, T2.DESCRIPTION FROM TB_DATA T1, TB_CODE T2 WHERE T1.C…

mysql主鍵 命中率_mysql主鍵問題

MySQL主鍵一. MySQL主鍵設計原則MySQL主鍵應當是對用戶沒有意義的。MySQL主鍵應該是單列的,以便提高連接和篩選操作的效率(當然復合主鍵是可以的,只是不建議)永遠也不要更新MySQL主鍵MySQL主鍵不應包含動態變化的數據,如時間戳、創建時間列、…

Centos7常用命令[掛載文件系統]

Centos7常用命令[掛載文件系統]------------------------------------------------------------------------------# 掛載一個叫做hda2的盤-確定目錄/mnt/hda2已經存在[rootlocalhost ~]# mount /dev/hda2 /mnt/hda2# 卸載一個叫做hda2的盤-先從掛載點/mnt/hda2退出[rootlocalh…

hadoop SecondNamenode

一、定義 * The Secondary Namenode is a helper to the primary Namenode. * The Secondary is responsible for supporting periodic checkpoints * of the HDFS metadata. The current design allows only one Secondary * Namenode per HDFs cluster. * The Secondary Nam…

Tensorflow Python API 翻譯(sparse_ops)

作者:chen_h 微信號 & QQ:862251340 微信公眾號:coderpai 我的博客:請點擊這里計劃現將 tensorflow 中的 Python API 做一個學習,這樣方便以后的學習。 原文鏈接該章介紹有關稀疏張量的API稀疏張量表示對于多維稀疏…

高性能mysql 小查詢_高性能MySql進化論(十一):常見查詢語句的優化

總結一下常見查詢語句的優化方式1 COUNT1. COUNT的作用 COUNT(table.filed)統計的該字段非空值的記錄行數 COUNT(*)或者是COUNT(not nullable field) 統計的是全表的行數如果要是統計全表記錄數,COUNT(*)效率會比COUNT(not nullable fie…

ORA-01861: 文字與格式字符串不匹配

select to_date(20160401000000,yyyy-mm-dd) from dual; ---------- 報錯:ORA-01861: 文字與格式字符串不匹配 原因:字符串20160401000000與要轉換的格式 yyyy-mm-dd 格式不對。 20160401000000 是 yyyymmddhh24miss 格式的 -------- select to_da…