Đêm khuya, hệ thống trading của tôi báo lỗi ConnectionError: timeout after 30s khi cố gắng lấy dữ liệu từ 5 sàn giao dịch cùng lúc. Đó là khoảnh khắc tôi nhận ra: xử lý đồng bộ (synchronous) không còn đủ cho trading thời gian thực. Bài viết này sẽ chia sẻ cách tôi xây dựng framework xử lý bất đồng bộ (asyncio) để handle hàng triệu data point mỗi ngày với độ trễ dưới 50ms.

Vì Sao Xử Lý Bất Đồng Bộ Quan Trọng Trong Trading?

Khi bạn cần lấy dữ liệu từ nhiều sàn (Binance, Coinbase, Kraken...) theo cách đồng bộ:

Với asyncio, tất cả requests chạy song song:

Kiến Trúc Framework Xử Lý Bất Đồng Bộ

1. Class Cơ Bản: AsyncExchangeConnector

import asyncio
import aiohttp
from typing import Dict, List, Optional
from dataclasses import dataclass
from datetime import datetime
import json

@dataclass
class TickerData:
    symbol: str
    price: float
    volume_24h: float
    change_24h: float
    timestamp: datetime
    exchange: str

class AsyncExchangeConnector:
    """
    Kết nối bất đồng bộ với nhiều sàn giao dịch
    Thiết kế: Non-blocking I/O với asyncio
    """
    
    def __init__(self, timeout: int = 10):
        self.timeout = timeout
        self.session: Optional[aiohttp.ClientSession] = None
        self._rate_limiter = asyncio.Semaphore(5)  # Tối đa 5 requests đồng thời
        
    async def __aenter__(self):
        connector = aiohttp.TCPConnector(
            limit=100,           # Tối đa 100 connections
            limit_per_host=10,   # Tối đa 10 connections/sàn
            ttl_dns_cache=300    # Cache DNS 5 phút
        )
        self.session = aiohttp.ClientSession(
            connector=connector,
            timeout=aiohttp.ClientTimeout(total=self.timeout)
        )
        return self
        
    async def __aexit__(self, *args):
        if self.session:
            await self.session.close()
    
    async def fetch_binance_ticker(self, symbol: str) -> Optional[TickerData]:
        """Lấy ticker từ Binance với xử lý lỗi"""
        url = f"https://api.binance.com/api/v3/ticker/24hr?symbol={symbol}"
        
        async with self._rate_limiter:  # Kiểm soát concurrency
            try:
                async with self.session.get(url) as response:
                    if response.status == 200:
                        data = await response.json()
                        return TickerData(
                            symbol=symbol,
                            price=float(data['lastPrice']),
                            volume_24h=float(data['quoteVolume']),
                            change_24h=float(data['priceChangePercent']),
                            timestamp=datetime.fromtimestamp(data['closeTime']/1000),
                            exchange='binance'
                        )
                    elif response.status == 429:
                        # Rate limit - retry với exponential backoff
                        await asyncio.sleep(2 ** 2)  # 4 giây
                        return await self.fetch_binance_ticker(symbol)
                    else:
                        print(f"Binance error: {response.status}")
                        return None
            except asyncio.TimeoutError:
                print(f"Timeout fetching {symbol} from Binance")
                return None
            except Exception as e:
                print(f"Error Binance: {e}")
                return None

Sử dụng

async def main(): async with AsyncExchangeConnector(timeout=10) as connector: # Lấy 10 cặp tiền song song symbols = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'ADAUSDT', 'DOGEUSDT', 'XRPUSDT', 'DOTUSDT', 'LTCUSDT', 'LINKUSDT', 'MATICUSDT'] tasks = [connector.fetch_binance_ticker(s) for s in symbols] results = await asyncio.gather(*tasks, return_exceptions=True) valid_results = [r for r in results if isinstance(r, TickerData)] print(f"Lấy thành công: {len(valid_results)}/{len(symbols)} tickers")

Chạy

asyncio.run(main())

2. Stream Processing Với Queue

import asyncio
from collections import deque
from typing import Callable, Awaitable

class AsyncDataStream:
    """
    Luồng dữ liệu bất đồng bộ với buffering và backpressure
    Phù hợp: Xử lý real-time data từ WebSocket streams
    """
    
    def __init__(self, maxsize: int = 1000):
        self._queue: asyncio.Queue = asyncio.Queue(maxsize=maxsize)
        self._running = False
        self._processors: List[Callable] = []
        
    async def put(self, item):
        """Thêm data vào stream - blocking nếu queue full"""
        await self._queue.put(item)
        
    async def get(self):
        """Lấy data từ