翻譯系統(tǒng) 5/14/2019更新

第二版 (5/14/2019更新)

React component example

<LanguageResource key = checkout.cfmMoney>Confirm Amount</LanguageResource>

數(shù)據(jù)庫設(shè)計

Language Resource Table Schema
Key, OriginContent, LastUpdated, ContentLangId1, LastUpdatedLangId1, ContentLangId2, LastUpdatedLangId2, ...
Key一定是要有比較規(guī)范的name space, 避免出現(xiàn)同一個key被不同的developper使用修改。

Task Table Schema
Key, OriginContent, LastUpdated, LanguageId, TranslatorId, status, HtmlFileLink, prioritiy

一種做法: 網(wǎng)頁修改完畢不等翻譯完成就上線。

網(wǎng)頁文件修改之后一種做法是直接deploy,用戶load頁面的時候會產(chǎn)生翻譯請求。
這種做法的考慮基于是很多時候某個頁面在某種語言很少會出現(xiàn),沒必要等全部翻譯完再上線。
根據(jù)用戶load的時候如果某個key找不到,就會自動產(chǎn)生一個translation request, 同時用英語做為fall back。 一個key被Request的次數(shù)越多他的優(yōu)先級越高,

API:

GetTranlantion(key, originContent, url)
this API call may make internal call: RequestTranslatorService(key, originContent, url)

單詞內(nèi)容有變化? OriginalContent修改的情況

如果這個key的英文改了: 在translation的時候就會發(fā)現(xiàn)送過去的originalLanguageContent的數(shù)據(jù)庫里的不一致!這種情況要做三件事情: 1。 更新數(shù)據(jù)庫里的original content, 2。 更新originalContent 的last update time。 3. send update translation request.

如果翻譯還沒更新又來訪問這個request了, 雖然內(nèi)容一致,但翻譯和原文的timestamp順序相反,這時仍然使用舊的翻譯,同時再發(fā)一次translation request.

updateTranslationAsOriginalContentUpdated(key, previousContent, newContent)

如果嫌慢(因?yàn)橐獙懞芏鄠€任務(wù))可以丟到一個message Queue里面去異步執(zhí)行。

key , originalcontent, translantion.

如何翻譯

getTranslation(key, OriginalLanguageContent, languageId)

如果找到,originalContent一致并且翻譯的timestamp比數(shù)據(jù)庫里originalContent的時間stamp要晚,則直接返回。如果找到但內(nèi)容不一致/timestamp不對 則refer to original content修改的情況。

如果找不到就fall back為英語,同時增加一個翻譯請求。這個翻譯請求如果已經(jīng)在task list里了,就更新優(yōu)先級, 如果不在, 就新建。

如何給翻譯員分配任務(wù)

根據(jù)翻譯員的語言種類,從當(dāng)前任務(wù)列表里先擇優(yōu)先級最高的一組翻譯,最好是據(jù)有相同key前綴的(一般優(yōu)先級也會相同, 因?yàn)橐粋€頁面里的key是同時更新優(yōu)先級的)。同時更新Task table把當(dāng)前任務(wù)設(shè)為pending,翻譯員id也設(shè)置上. 這樣別的翻譯員就不會去拿同一個task。 可以再增加一個field記一下任務(wù)是什么時候開始的。如果一段時間任務(wù)并沒有完成,則自動重新變成available.

getTranslationTask(languageId, amount, translatorId);

翻譯員如何更新翻譯

Api: enterTranslation(key, languageId, translated content, translatetimeStamp, originContentTimeStamp)

在更新數(shù)據(jù)庫時候先check一下數(shù)據(jù)庫里original content的time stamp, 如果翻譯人員提交的original content的timestamp比較老, 則拒絕這次更新,返回outdated originalContent Exception.

如果更新成功, 則把更新的信息broadcast給所有存有cache的web服務(wù)器。也可以定期推送。

另外一種做法翻譯完再上線。

另外一種做法是網(wǎng)頁修改之后,直接extract新的key和修改過的key value pair. 這些key不翻譯完新版網(wǎng)頁就不上線。

Api: ExtractForTranslation(fileName) return a jobId

Using this jobId, the developper can see how much content has been already translated

全部翻譯完成后翻譯官把整個翻譯的package發(fā)過來。發(fā)過來之后由系統(tǒng)統(tǒng)一deploy。但這樣會delay上線速度。 此時翻譯官也不會直接把翻譯輸入數(shù)據(jù)庫。因?yàn)樾戮W(wǎng)頁還沒上線, 翻譯先上線會造成數(shù)據(jù)不一致。

Scale

可以把兩張表都放到數(shù)據(jù)庫里面。 Lanaguage Resource Table直接在每個webserver上做cache。如果數(shù)據(jù)庫有更新,數(shù)據(jù)庫服務(wù)器就會notify 其他所有的webserver更新cache??梢悦渴昼娮鲆淮?。

如何Sharding:

由于數(shù)據(jù)量不大,本身不一定需要sharding??梢园凑Z言和對應(yīng)的location sharding。

Indexing

LanguageResource直接按key查+就可以了, 本身就有index, 不需要再建index。

對于task Table要按 languageId + 狀態(tài) 建 index,

task Table的primary index是 key + languageId,

每天半夜12點(diǎn)可以更新一下優(yōu)先級,讓所有的優(yōu)先級衰減。刪掉那些低于某些threhold的值。

-----------------------------我寫的翻譯系統(tǒng)第二版到這里結(jié)束-------------------------------------------------------------

參考文獻(xiàn):

相關(guān)的官方技術(shù)博客
https://medium.com/airbnb-engineering/launching-airbnb-jp-in-record-time-52f8b0af965d
技術(shù)文檔 https://airbnb.io/polyglot.js/
其他 https://www.jiuzhang.com/qa/5054/ https://github.com/donnemartin/system-design-primer

4S 分析大法

Scenario:

前端人員使用一種語言(比如英語)設(shè)計前端。
menu label, 描述,免責(zé)條款,
前端人員release 英文版網(wǎng)頁或內(nèi)容 ==》 觸發(fā)翻譯系統(tǒng)extract 翻譯事件 :翻譯系統(tǒng)分析英文版文件,對比哪些句子/內(nèi)容已經(jīng)翻譯過了,哪些句子/內(nèi)容需要新翻譯。==》 extract出新句子分發(fā)給翻譯員。==》翻譯員完成翻譯任務(wù)之后返回給翻譯系統(tǒng)。翻譯系統(tǒng)輸出多種語言包。

系統(tǒng)可以分為兩種實(shí)現(xiàn)形式:

如果是網(wǎng)頁更新比較慢而且是一組靜態(tài)網(wǎng)頁的話。

1。前端人員 2。 網(wǎng)頁分析服務(wù)。 3數(shù)據(jù)庫 4。 Combine 服務(wù) 5。翻譯員。
這樣的話,所有的內(nèi)容在創(chuàng)建的時候都立馬翻譯好,可能有幾個小時到一兩天的delay。
這種的缺點(diǎn)是所有語言版本的發(fā)布會比較慢,因?yàn)樗袃?nèi)容都要翻譯。

如果是像Airbnb這樣的動態(tài)生成的網(wǎng)頁(數(shù)據(jù)都是數(shù)據(jù)庫里調(diào)出來的)

前端人員修改網(wǎng)頁的時候,可以在修改完網(wǎng)頁時自動發(fā)一個翻譯的request 通知系統(tǒng)去翻譯,但可能網(wǎng)頁還沒翻譯完就上線了。
用戶輸入airbnb.cn網(wǎng)站地址,根據(jù)用戶的地理語言信息,webserver在生成網(wǎng)頁的時候發(fā)一個translate request. 把網(wǎng)頁里對應(yīng)的標(biāo)簽轉(zhuǎn)換成相應(yīng)的語言再返回給用戶。相當(dāng)于一個實(shí)時的翻譯系統(tǒng)。不需要等待頁面全部翻譯完成再上線。如果一個詞在本地cache里,先查本地cache, 如果不在本地cache,則可以跨過網(wǎng)絡(luò)去查數(shù)據(jù)庫的cache,如果數(shù)據(jù)庫的cache里面也沒有,則去數(shù)據(jù)庫里找,找不到就用默認(rèn)語言并且去待翻譯數(shù)據(jù)庫里面給該key增加一下優(yōu)先級。 一個key被request的次數(shù)越多,它的優(yōu)先級越高。

翻譯人員從“待翻譯數(shù)據(jù)庫” 里拿出當(dāng)前優(yōu)先級最高的詞, 翻譯,輸入系統(tǒng)。

API

GetTranslate(key, default, locale)
EnterTranslatedVersion(key, default, value, locale)
如果要改key 和default的話, 可以增加一個api, updateTranslate(key, new default, locale)

需要設(shè)計多牛的系統(tǒng)

怎么估算size??
還真不知道。 算一下有多少網(wǎng)頁:每個網(wǎng)頁有多少單詞??還得再想想

Service

Translate Service
Translator task service

Client     -->        webServer 
                            |
                            v
Front End -> Translate Service ->    DataBase
                                         ^
                                         |
                                         v
Translator   <-->       Translate Task Service 

Storage

Data model

Translation Table

用什么數(shù)據(jù)庫? Redis (內(nèi)存型), Cassandra, SQL + Memcached

Redis是純粹的key -value pair: 如果用Redis
Key:Key + Locale, Value : content in language of locale + time stamp

如果用Cassandra, 三層結(jié)構(gòu)。
Schema:
Row Key : Key ;
Column Key: Locale
Value: content in some language + time stamp
讀取的時候要用Key + locale去讀。

也可以用SQL,反正是讀多寫少,大不了用cache優(yōu)化一下。
SQL也行。。。因?yàn)槟膬耗拿炊嘣L問量

Task Table

這個量級很小,一個SQL就足夠了。
Schema如下
Key,Original Language, To Language,優(yōu)先級, status,

Working solution

前端人員把 key, English

優(yōu)化:

按優(yōu)先級排序,如果一個key被call的次數(shù)越多,優(yōu)先級越高。 如果一個key四天都沒有被call過,則自動清除出隊列。

加速 優(yōu)化perf

在Web Server端放一些Cache,有問題先查本地的cache,查不到再找DB。
建index, 只需要根據(jù)key 和locale建一個composite primary index就可以了。
bloom filter : 如果一個key不在bloom filter里面,則肯定不用找了。

關(guān)鍵問題: 如果DB更新了,如何第一時間更新那么多server:

DB主動發(fā)送push notification給Web Server.
需要設(shè)計TTL嗎? 最好這樣,不然如果某些push notification某種原因沒有收到,就跪了。

Sharding

如果需要Sharding,則可以按語言按距離按國家Sharding。
非要按Hash code sharding的話,sharding key就是我們的key。其實(shí)并不需要sharding,一臺機(jī)器是可以搞定的。
Consistent hashing 的概念
按String做為sharding key

Cache

Cache thru 和Cache aside都可以。但重要的是在服務(wù)器端直接cache, 就不用每次訪問數(shù)據(jù)庫了。

前端程序員不受后端設(shè)計的影響。

前端用key,和 value寫在html里面。

translator有另一個portal輸入翻譯而且能馬上看到效果

把對應(yīng)的html存下來,直接調(diào)存下來的html顯示。

再來就是有時候translator翻譯錯了修改之后怎么樣才能更快的讓大家看見(如果你有cache的話)

Broadcast,Server和DB 保持一個長鏈接,有新的變化立馬通知。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容