2017年,我們贏得了開發阿爾法銀行投資業務交易核心的競賽並開始工作(在 HighLoad++ 2018 上發表了關於投資業務核心的報告)
在開發過程中,系統不斷發展並獲得了功能,在某種程度上,我們意識到我們正在具體化一些東西,而不僅僅是為了解決嚴格定義的任務範圍而創建的應用程式軟體:我們成功了 用於建立具有持久性儲存的分散式應用程式的系統。 我們所獲得的經驗構成了新產品的基礎 -
我想談談 TDG 架構和我們在開發過程中提出的解決方案,向您介紹主要功能,並展示我們的產品如何成為建立完整解決方案的基礎。
在架構上,我們將系統分為獨立的 角色,每個都負責解決一定範圍的問題。 單一正在運行的應用程式實例實作一種或多種角色類型。 叢集中可以有多個相同類型的角色:
連接器
Connector負責與外界溝通; 它的任務是接受請求,解析它,如果成功,則將資料傳送到輸入處理器進行處理。 我們支援 HTTP、SOAP、Kafka、FIX 格式。 該架構允許您簡單地添加對新格式的支持,並且即將推出對 IBM MQ 的支援。 如果解析請求失敗,連接器將回傳錯誤; 否則,即使在進一步處理過程中發生錯誤,它也會回應請求已成功處理。 這樣做是專門為了與不知道如何重複請求的系統一起工作 - 或者相反,過於持久地這樣做。 為了不丟失數據,使用修復隊列:物件首先進入其中,只有在成功處理後才從其中刪除。 管理員可以接收有關修復佇列中剩餘物件的警報,並在消除軟體錯誤或硬體故障後重試。
輸入處理器
輸入處理器根據特徵特徵對接收到的資料進行分類,並呼叫適當的處理器。 處理程序是在沙箱中運行的 Lua 程式碼,因此它們不會影響系統的功能。 在此階段,可以將資料簡化為所需的形式,如果需要,可以啟動任意數量的任務來實現必要的邏輯。 例如,在基於 Tarantool Data Grid 建構的 MDM(主資料管理)產品中,當新增使用者時,為了不減慢請求的處理速度,我們將建立黃金記錄作為單獨的任務啟動。 沙箱支援讀取、變更和新增資料的請求,可讓您對儲存類型的所有角色執行某些功能並聚合結果(映射/減少)。
處理程序可以在文件中描述:
sum.lua
local x, y = unpack(...)
return x + y
然後,在配置中聲明:
functions:
sum: { __file: sum.lua }
為什麼是盧阿? Lua 是一種非常簡單的語言。 根據我們的經驗,在了解它幾個小時後,人們就開始編寫解決他們問題的程式碼。 這些人不僅是專業開發人員,也是分析師等。 另外,由於jit編譯器,Lua運作速度非常快。
儲存應用
儲存儲存持久性資料。 儲存之前,將根據資料模式驗證資料。 為了描述電路,我們使用擴展格式
{
"name": "User",
"type": "record",
"logicalType": "Aggregate",
"fields": [
{ "name": "id", "type": "string"},
{"name": "first_name", "type": "string"},
{"name": "last_name", "type": "string"}
],
"indexes": ["id"]
}
基於此描述,自動為 Tarantula DBMS 產生 DDL(資料定義語言)並
支援非同步資料複製(有計劃增加同步)。
輸出處理器
有時需要通知外部消費者新資料的到達;為此,需要輸出處理器角色。 儲存資料後,可以將其傳遞給相應的處理程序(例如,將其變為消費者所需的形式)—然後傳遞給連接器進行傳送。 這裡也使用了修復佇列:如果沒有人接受該對象,管理員可以稍後再試。
縮放
連接器、輸入處理器和輸出處理器角色是無狀態的,允許我們透過簡單地新增啟用所需角色類型的新應用程式實例來水平擴展系統。 儲存用於水平擴展
資料屬性
物件可以非常大並且包含其他物件。 我們透過將具有所有依賴項的物件儲存在一個虛擬儲存桶中來確保新增和更新資料的原子性。 這可以防止物件「分散」到多個實體伺服器上。
支援版本控制:物件的每次更新都會創建一個新版本,我們始終可以獲得一個時間片並查看當時的世界是什麼樣子。 對於不需要很長歷史記錄的數據,我們可以限製版本數量,甚至只儲存一個(最新的版本),也就是說,本質上禁用某種類型的版本控制。 您也可以按時間限制歷史記錄:例如,刪除超過 1 年的某種類型的所有物件。 也支援歸檔:我們可以卸載早於指定時間的對象,從而釋放叢集中的空間。
任務
在這些有趣的功能中,值得注意的是能夠按計劃、根據用戶的請求或以編程方式從沙箱啟動任務:
這裡我們看到了另一個角色──跑者。 該角色是無狀態的,可以根據需要將具有該角色的其他應用程式實例新增至叢集中。 跑步者的責任是完成任務。 如前所述,可以從沙箱產生新任務; 它們保存在儲存上的佇列中,然後在運行器上執行。 這種類型的任務稱為作業。 我們還有一個名為「任務」的任務類型 - 這些是使用者定義的任務,按計劃(使用 cron 語法)或按需運行。 為了啟動和追蹤此類任務,我們有一個方便的任務管理器。 為了使此功能可用,您必須啟用調度程序角色; 該角色有一個狀態,因此它無法擴展,但這不是必需的; 同時,與所有其他角色一樣,它可以有一個副本,如果主伺服器突然拒絕,該副本就會開始工作。
記錄儀
另一個角色稱為記錄器。 它收集群集所有成員的日誌,並提供一個透過 Web 介面上傳和查看日誌的介面。
服務
值得一提的是,該系統使得創建服務變得容易。 在設定檔中,您可以指定將哪些請求傳送到在沙箱中執行的使用者編寫的處理程序。 例如,在此處理程序中,您可以執行某種分析查詢並傳回結果。
該服務在設定檔中描述:
services:
sum:
doc: "adds two numbers"
function: sum
return_type: int
args:
x: int
y: int
GraphQL API 會自動生成,且服務可供呼叫:
query {
sum(x: 1, y: 2)
}
這將調用處理程序 sum
這將返回結果:
3
查詢分析和指標
為了了解系統的操作和分析請求,我們實現了對 OpenTracing 協定的支援。 系統可以按需向支援該協定的工具(例如 Zipkin)發送訊息,這將使您了解請求是如何執行的:
當然,系統提供了可以使用 Prometheus 收集並使用 Grafana 視覺化的內部指標。
部署
Tarantool 資料網格可以使用發行版或 Ansible 中的公用程式從 RPM 套件或檔案進行部署,也支援 Kubernetes (
實作業務邏輯(配置、處理程序)的應用程式透過 UI 或透過我們提供的 API 使用腳本以存檔的形式載入到已部署的 Tarantool Data Grid 叢集中。
範例應用程式
使用 Tarantool 資料網格可以創建哪些應用程式? 事實上,大多數業務任務在某種程度上與處理、儲存和存取資料流相關。 因此,如果您有大量資料流需要安全儲存和訪問,那麼我們的產品可以為您節省大量開發時間並專注於您的業務邏輯。
例如,我們希望收集有關房地產市場的信息,以便將來我們可以獲得有關最佳報價的信息。 在這種情況下,我們將突出以下任務:
- 從開源收集資訊的機器人將成為我們的資料來源。 您可以使用現成的解決方案或用任何語言編寫程式碼來解決此問題。
- 接下來,Tarantool 資料網格將接受並保存資料。 如果不同來源的資料格式不同,那麼您可以在 Lua 中編寫程式碼來執行到單一格式的轉換。 例如,在預處理階段,您還可以過濾重複的報價或另外更新資料庫中有關市場中工作的代理商的資訊。
- 現在,您在叢集中已經有了一個可擴展的解決方案,可以填入資料並進行資料選擇。 然後您可以實現新功能,例如,編寫一個服務來請求資料並每天提供最優惠的報價 - 這將需要設定檔中的幾行和一些 Lua 程式碼。
接下來是什麼?
我們的首要任務是提高開發的便利性
我們也非常注重安全問題。 目前我們正在接受俄羅斯FSTEC的認證,以確認其高安全級別,並滿足個人資料資訊系統和政府資訊系統中使用的軟體產品的認證要求。
來源: www.habr.com