前言
我最近參與了公司的一個新項目,需要通過openapi接口把接入方
的數據,比如:企業、訂單、合同、物流等,同步到我們平台,然后我們平台給他們提供金融能力。
由於我方
跟對接方
不在同一個城市,為了提高工作效率,雙方進行了多次在線視頻溝通。剛開始比較順利,沒想到在溝通企業信息上傳接口時,接口文檔中有個非常不起眼的企業注冊地id
字段,讓我們一下子進入了僵局。
到底是怎么回事呢?
1.地區問題
在我們平台的企業表
中有一個企業注冊地id
字段,是必填的,用戶在注冊企業的頁面需要選擇一個地區,作為該企業的注冊地,實際上數據庫保存的是地區的id。
如果該企業注冊成功了,會在企業詳情頁面上展示該地區名稱。當然我們系統的后台邏輯是先通過地區id
到地區表
反查出地區名稱,然后在用戶界面中展示出來。
為了跟企業表
保持一致,我方在定義接口文檔時,企業注冊地id字段也做成必填了。
當時的情況是這樣的:我方地區表中有id、地區名稱、國標碼、等級等字段,但這里的id,是我方數據庫的主鍵,對接方系統中肯定是沒有的。對接方系統中也有一套地區表,不過id是他們的數據庫id,他們的表中也有地區名稱、國標碼、等級等字段。
所以他們系統內部需要經過一番轉換,才能把我們所需的地區id傳給我們。
1.1 持久化本地地區表
其實這個項目我是中途才加入的,之前在處理別的事情,我加入的時候接口文檔已經定義好了。
我方跟對接方進行第二次在線溝通的時候,雙方一起過接口文檔的細節,包括:接口的作用、每個參數的含義,以及他們是否有值傳過來等等。
其中過到企業信息上傳接口時,接口文檔中有個企業注冊地id
字段,對方沒法傳值過來。為了解決這個問題,我方第一版的方案是:
- 對接方調用我方地區查詢接口,通過多次分頁查詢,最終能獲取我方所有地區數據,落庫到他們本地的地區表。
- 他們在調用我方企業信息上傳接口之前,先查詢本地的地區表,轉換成我方所需要的地區id。
在討論的過程中,對接方覺得他們也是平台,不應該做這些額外的事情。所以在那次會議中,雙方針對這個問題,誰也沒有說服誰,最終也沒能達成共識。
后來,我思考了一下,確實這個方案太過理想化了,沒有真正站到用戶的角度思考問題,忽略了很多細節。可能跟文檔設計者不對地區表不太熟悉有關系。
1.2 按名稱調用地區查詢接口
那次會議當中,我們這邊的幾位同事,短暫的討論了一下。既然對接方不願意接受在他們本地持久化地區表,我們就退而求其次,不要求他們持久化了。這時我們這邊有個同事提出,改成按名稱調用地區查詢接口,反查出地區id,具體方案如下:
這個方案表面上看起來沒有問題,但我之前負責過區域相關功能,我知道,就怕出現如下情況:
- 如果對接方傳的地區名稱不完整,比如:本來是
成都市
,實際上傳的成都
。這樣,我們地區查詢接口,需要做模糊匹配,如果並發調用接口可能影響接口性能。 - 如果輸入關鍵字
北京市
,在我們這邊的地區表中,可以找到兩條數據,一條是跟省級別
一樣的,另一條是跟市級別
一樣的。到底對應哪條數據呢?
所以我當時把這兩個問題拋出來了,不建議使用地區名稱查詢。
1.3 按國標碼調用地區查詢接口
那個同事聽完之后,也覺得用地區名稱查詢有點不靠譜。他馬上修改方案,改成使用地區的國標碼查詢地區id,具體方案如下:
由於當時討論時間非常短,我們沒來得及考慮太多,暫且打算用這套方案。
1.4 企業上傳接口入參傳國標碼
過了一會兒,雙方繼續過接口文檔,重新討論企業信息上傳接口中企業注冊地id
字段傳值問題。
他們在調企業信息上傳接口之前,先調一下我們地區查詢接口,查出地區id,入參是國標碼。然后再將這個地區id,在企業信息上傳接口中傳過來。
對接方仔細聽了我們的方案,猶豫了一下,他們覺得沒有必要再調一次地區查詢接口,雙方都使用國標碼不就行了?
他們的想法是:在企業信息上傳接口中,入參由企業注冊地id
改成企業注冊地國標碼
,由於國標碼是國家統一的唯一編碼,雙方肯定是一樣,能保證數據的一致性。
2.想起了一個問題
說實話,如果你沒接觸過地區功能的話,大部分人可能會同意這套方案的。
但比較巧合的是我之前正好接觸過類似的功能,當時我突然想起了一個問題:雙方數據的一致性如何保證?
我們都知道,由於國家的發展,有些城市可能會改名,比如:襄樊
改成了襄陽
,另外有時候多個地級市合並成一個市,這樣國標碼會變化,所以國家統計網每年都會調整地區名稱和國標碼。
我方的地區表是兩年之前創建的,數據初始化好之后沒有就更新過。
而對接方不是跟我們在同一時刻初始化的數據,而且他們會定期更新地區數據,這樣就導致了兩邊的數據不一致。如果對接方的業務表單中使用了新加的城市名和國標碼,而這些信息在我方的地區表中沒有,就無法查詢出我方所需的地區id。
這種情況該怎么辦?
2.1 雙方同一時刻更新地區表
顯然上面的問題是一個非常棘手的問題,這時候有些小伙伴可能會說:雙方使用job同一時刻更新地區表
,不就能解決問題了?
我不太贊成這種方案,主要原因如下:
- 我方僅跟這個對接方有個同步執行的job,沒問題。但如果還有其他的對接方,也需要調用企業信息上傳接口,是不是也要整一個job,而且還要求大家都同一時刻執行,耦合性太大了。
- 如果我方和對接方同時執行job,但萬一有任意一方執行失敗了,也會導致數據不一致的情況。如果恰好這時候對接方在調用企業信息上傳接口,會不會出問題?
2.2 以一方的地區數據為准?
上面的雙方同一時刻更新地區表的方案確實有點不靠譜,但有些讀者可能會問,以一方的地區數據為准,另一方把數據同步過來不就行了。具體方案如下:
這個方案其實跟之前我方給出的第一個方案很相似,已經被對接方拒絕了。站在他們的角度來說,確實沒有必要因為上傳企業信息,而保存我們的地區數據。
說實話,即使他們同意了,這種跨公司跨系統的數據一致性問題,也不好保證,因為如果對接方調用我們的地區接口失敗了,此時,正好在上傳企業信息,是不是也有問題?
我們一下子進入了困境,但為了不影響整體進度,只能先記錄一下問題,然后跳過這個問題,繼續討論其他字段了。
3.如何解決這個問題?
我當天晚上思考了良久,第二天早上,發現跟我們老大的想法不謀而合。得出的結論是,既然存在差異化,沒辦法避免,我們就要從系統設計上接受差異化。在企業信息上傳接口中增加兩個字段:企業注冊地國標碼
和 地區名稱
,對接方改成傳入這兩個字段,具體方案如下:
- 在我方的企業表中增加地區名稱字段,是非必填的,同時把之前的地區id字段也改成非必填。
- 對接方在調用我方企業信息上傳接口時,同時傳入地區國標碼和地區名稱。
- 我方企業信息上傳接口中判斷,如果通過國標碼能夠找到地區id,則將地區id寫入db,如果找不到,則將地區名稱寫入db。
我們評估了一下影響范圍,在企業表中的地區字段,只做展示用,沒有修改入口,所以上面的這套方案是可行的。
后來,再次跟對接方在線溝通時,把我們的這套方案告訴他們了,他們非常贊同。
4 總結
雖說這個地區問題,在眾多技術問題中不值得一提。但是我仔細思考了一下,還是有一些寶貴的經驗值得總結一下的,給有需要的小伙伴一個參考。
4.1 要從用戶的角度設計接口
在設計接口文檔時,要真正做到從用戶的角度出發。
尤其是像這種openapi接口,定義的參數應該盡量選擇通用的,大家都認可的參數,避免出現我方定制化的參數,比如:地區id。
盡量減少用戶的復雜度,讓他們調用接口時更簡單一些。
4.2 技術方案要有包容性
技術方案要有包容性,不是非黑即白,需要有柔性的思想。在分布式環境中,如果去一味地追求數據的強一致性,不會有太好的結果。就像高並發下的商品秒殺系統,如果非要用同步方案去實現,系統最終可能會掛掉,更好的方案其實是改成異步隊列處理。
我方和對接方都有地區表,數據很難保證完全一致,我們不要為了一致性而一致性,這樣會適得其反。為了工作能夠順利進行下去,必然有一方要妥協,我的建議是openapi接口方做妥協,這種技術方案才夠通用。
4.3 沒有最好的方案,只有最適合的
我方最后的那個方案,其實並沒有完全解決地區id找不到的問題,但是從業務的角度來看,即使沒有地區id,有地區名稱也是一樣的。很顯然,最后的方案是非常適合我們實際業務場景的。
所以沒有最好的方案,只有最適合業務場景的。
4.4 進行有效的溝通
在跟對接方在線溝通時,不要因為某個問題卡殼了,而一直僵持下去。如果當時沒有好的技術方案,可以先選擇暫時跳過這個問題,而溝通其他的內容。后面我們再私下單獨花時間,仔細思考當時的問題,從而能夠提出更合理的方案。
最近無意間獲得一份BAT大廠大佬寫的刷題筆記,一下子打通了我的任督二脈,越來越覺得算法沒有想象中那么難了。
[BAT大佬寫的刷題筆記,讓我offer拿到手軟](這位BAT大佬寫的Leetcode刷題筆記,讓我offer拿到手軟)
最后說一句(求關注,別白嫖我)
如果這篇文章對您有所幫助,或者有所啟發的話,幫忙掃描下發二維碼關注一下,您的支持是我堅持寫作最大的動力。
求一鍵三連:點贊、轉發、在看。
關注公眾號:【蘇三說技術】,在公眾號中回復:面試、代碼神器、開發手冊、時間管理有超贊的粉絲福利,另外回復:加群,可以跟很多BAT大廠的前輩交流和學習。