Trong lĩnh vực Crypto, Chứng khoán hoặc Ngoại hối, tốc độ và hiệu suất đóng vai trò quan trọng, đặc biệt đối với Matching Engine – hệ thống xử lý các lệnh mua và bán. Ring Buffer là một cấu trúc dữ liệu dạng vòng, giúp cải thiện hiệu suất của sàn giao dịch bằng cách giảm chi phí sử dụng bộ nhớ và đảm bảo luồng dữ liệu ổn định. Bài viết này cung cấp hướng dẫn toàn diện về cách xây dựng Matching Engine sử dụng Ring Buffer.
Matching Engine (ME – Hệ thống Khớp lệnh)
1. Định nghĩa
2. Cách thức hoạt động
- Receiving order: Matching Engine tiếp nhận các lệnh mua hoặc bán từ người dùng, bao gồm các thông tin như mã giao dịch (Symbol), giá, số lượng và loại lệnh (Market Order, Limit Order,...).
- Order Storage: Các lệnh được lưu trữ trong Order Book, Order bookbao gồm hai danh sách chính:
- Buy OrdersDanh sách các lệnh mua được sắp xếp theo thứ tự giá giảm dần.
- Sell OrdersDanh sách các lệnh bán được sắp xếp theo thứ tự giá tăng dần.
- Order Matching: Matching Engine kiểm tra xem các lệnh mua và bán có thể được khớp hay không. Sau đó, các lệnh được khớp theo các quy tắc phổ biến:
- Price: Lệnh mua có thể khớp với lệnh bán nếu giá mua lớn hơn hoặc bằng giá bán.
- Time: Nếu có nhiều lệnh cùng mức giá, lệnh được đặt trước sẽ được ưu tiên.
- Trade Execution: Khi một lệnh mua và một lệnh bán được khớp, giao dịch sẽ được thực hiện. Số lượng tài sản được chuyển từ người bán sang người mua, đồng thời tiền được chuyển từ người mua sang người bán.
- Updating the order book: Sau khi giao dịch được thực hiện, Order Book sẽ được cập nhật để phản ánh các lệnh đã khớp và số lượng còn lại của các lệnh.
Ví dụ, chúng ta có hai lệnh:
- Buy order: 5 ETH với giá $100
- Sell Order: 2 ETH với giá $99
Khi lệnh bán 2 ETH với giá $99 được gửi lên, Matching Engine sẽ khớp lệnh này với lệnh mua đầu tiên trong Order Book. Kết quả là một giao dịch 2 ETH với giá $99 được thực hiện.Sau khi giao dịch hoàn tất, Matching Engine sẽ lưu phần số lượng còn lại của Buy Order vào hàng đợi lệnh mua, hoặc ngược lại tùy theo trường hợp.
3. Các loại lệnh phổ biến
- Market Order: Lệnh mua hoặc bán được thực hiện tại mức giá tốt nhất hiện tại.
- Limit Order: Lệnh mua hoặc bán được thực hiện tại mức giá chỉ định hoặc mức giá tốt hơn.
- Stop Order: Lệnh được kích hoạt khi giá đạt đến mức giá đã chỉ định.
- Stop-Limit Order: Lệnh được chuyển thành Limit Order khi giá đạt đến một mức giá cụ thể.
Tổng quan về Ring Buffer
1. Định nghĩa
- Kích thước cố định: Ring Buffer có kích thước cố định. Khi Buffer đầy, phần tử mới sẽ ghi đè lên phần tử cũ nhất.
- Hai con trỏ (Two Pointers): Head Pointer trỏ đến vị trí mới nhất, còn Tail Pointer trỏ đến vị trí cũ nhất.
- Sử dụng bộ nhớ hiệu quả (Efficient Memory Usage):: Ring Buffer không cần di chuyển dữ liệu khi ghi hoặc đọc, giúp tối ưu việc sử dụng bộ nhớ và cải thiện hiệu suất.
```bash
npm install react-native-maps or yarn add react-native-maps
``` 2. Các trường hợp sử dụng phổ biến
- Xử lý âm thanh hoặc video.
- Giao tiếp giữa các tiến trình.
- Hàng đợi trong các hệ thống thời gian thực.
<application>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="YOUR_GOOGLE_MAPS_API_KEY" />
</application> 3. Ưu điểm
- Hiệu suất cao do không cần di chuyển dữ liệu khi thêm hoặc xóa phần tử.
- Sử dụng bộ nhớ hiệu quả nhờ kích thước cố định.
4. Nhược điểm
- Kích thước cố định có thể trở thành hạn chế khi lượng dữ liệu thay đổi không dự đoán trước.
- Quản lý trạng thái đầy và rỗng phức tạp hơn.
5. Cách thức hoạt động
- Được triển khai trên một Array, sử dụng hai con trỏ: Tail và Head.
- Khi nhận lệnh ghi (Write), Head Pointer ghi dữ liệu vào Buffer, sau đó tăng vị trí lên 1.
- Khi nhận lệnh đọc (Read), dữ liệu được đọc từ Buffer, sau đó Tail Pointer tăng vị trí lên 1.
- Khi một con trỏ đến phần tử cuối cùng, nó sẽ tự động quay lại vị trí ban đầu.
Đây là đoạn lệnh:
// Does not allow overwriting
IF (TAIL + 1) === SIZE ( throw IS_FULL), TAIL = (TAIL + 1) % SIZE
Ví dụ:
SIZE = 5 ta có:
Buffer: [ , , , , ]
HEAD = 0
TAIL = 0
- Mở ios/Podfile và thêm các đoạn mã sau:
// Plus 1,
Buffer: [1, , , , ]
HEAD = 0
TAIL = 1
// Plus 2.
Buffer: [1, 2, , , ]
HEAD = 0
TAIL = 2
// Plus 3.
Buffer: [1, 2, 3, , ]
HEAD = 0
TAIL = 3
// Plus 4.
Buffer: [1, 2, 3, 4, ]
HEAD = 0
TAIL = 4
// Plus 5.
Buffer: [1, 2, 3, 4, 5]
HEAD = 0
TAIL = 5
// Plus 6.
Throw IS_FULL
// Pop
1,2,3,4,5
// Allows overwriting
IF (TAIL + 1) === SIZE HEAD = (HEAD + 1) % SIZE , TAIL = (TAIL + 1) % SIZE
// Plus 1.
Buffer: [1, , , , ]
HEAD = 0
TAIL = 1
// Plus 2.
Buffer: [1, 2, , , ]
HEAD = 0
TAIL = 2
// Plus 3.
Buffer: [1, 2, 3, , ]
HEAD = 0
TAIL = 3
// Plus 4.
Buffer: [1, 2, 3, 4, ]
HEAD = 0
TAIL = 4
// Plus 5.
Buffer: [1, 2, 3, 4, 5]
HEAD = 0
TAIL = 5
// Plus 6.
Buffer: [6, 2, 3, 4, 5]
HEAD = 0
TAIL = 1
// Plus 6.
Buffer: [6, 7, 3, 4, 5]
HEAD = 0
TAIL = 2
// POP HEAD start = 2
3,4,5,6,7
Khi áp dụng Ring Buffer vào Matching Engine, hệ thống có thể tối ưu quá trình xử lý các lệnh mua và bán một cách nhanh chóng và hiệu quả. Ring Buffer đảm bảo các lệnh được xử lý theo thứ tự FIFO, trong khi Order Book và thuật toán khớp lệnh đảm bảo các lệnh được khớp chính xác theo các quy tắc đã được thiết lập.
Demo: Ứng dụng Matching Engine và Ring Buffer trong giao dịch P2P
Trong bối cảnh giao dịch tài chính hiện nay, các hệ thống giao dịch P2P (Peer-to-Peer) ngày càng phổ biến nhờ tính minh bạch và hiệu quả. Để nâng cao hiệu suất và độ tin cậy của các hệ thống này, việc ứng dụng các công nghệ tiên tiến như Matching Engine (ME) và Ring Buffer là rất quan trọng.
Công nghệ sử dụng
Database: MYSQL
Backend: Java Spring boot
Front end: NextJs
Quy trình hoạt động
Data Diagram
Dưới đây là một ví dụ về dữ liệu đầu vào của người dùng.
Order type: Chọn loại lệnh bạn muốn thực hiện.
Price: Nhập mức giá bạn muốn.
Amount: Nhập số lượng Token bạn muốn mua hoặc bán.
Total: Hệ thống sẽ tự động tính tổng số USD cần thiết.
Các lớp xử lý chính
- P2POrderService
- MatchingEngineService
- P2PTransactionService
- UserWalletService
- RingBuffer
- UserCryptoWalletService
P2POrderService
Tiếp nhận các lệnh và đưa vào Ring Buffer để chờ Matching Engine xử lý. Service này gọi UserWalletService và UserCryptoWalletService để cập nhật số dư của người dùng.
Nếu loại giao dịch là BUY, hệ thống sẽ đóng băng số USD cần thiết trong ví của người dùng.
MatchingEngineService
Lần lượt lấy các lệnh từ Ring Buffer theo thứ tự FCFS (First Come, First Served) và khớp với các lệnh trước đó để thực hiện giao dịch P2P.
Các giao dịch được so sánh dựa trên các điều kiện sau:
* Buy order: Buy price >= Sell price
* Sell order: Sell price <= Buy price
* Cannot buy from oneself
* Tokens must be the same
Bạn có thể sử dụng @PostConstruct để khai báo một Ring Buffer duy nhất cho toàn bộ ứng dụng, với kích thước Buffer được cấu hình trong file application.
Cron Job sẽ gọi hàm processOrders mỗi phút.
@Scheduled(fixedRate = {milisecond})
Sau khi khớp lệnh thành công, MatchingEngineService sẽ gọi P2PTransactionService để lưu lịch sử giao dịch vào Database, bao gồm Buy Order, Sell Order, số lượng và giá.
Khai báo Ring Buffer
Class RingBuffer bao gồm các thuộc tính: size, head, tail, isFull.
Bằng cách áp dụng thuật toán Ring Buffer, chúng ta có thể khai báo hàm push để thêm một phần tử mới vào Buffer.
// Does not allow overwriting
IF (TAIL + 1) === SIZE ( throw IS_FULL), TAIL = (TAIL + 1) % SIZE
Các bước trên là toàn bộ quy trình giúp bạn xây dựng Matching Engine sử dụng Ring Buffer. Bạn có thể áp dụng các bước này để nâng cao hiệu suất cho các sàn giao dịch Crypto, Forex hoặc Chứng khoán. Nếu bạn muốn phát triển các sàn giao dịch này hoặc một ứng dụng cần Matching Engine, hãy liên hệHãy chia sẻ thông tin chi tiết về dự án và nhận báo giá từ chúng tôi.
Chúng tôi luôn sẵn sàng ký kết một NDA để bảo mật thông tin của bạn!















