- vừa được xem lúc

Redis và FastAPI - khi nào nên lựa chọn?

0 0 1

Người đăng: Hạ Hồng Sơn

Theo Viblo Asia

I. Redis là gì?

Redis (Remote Dictionary Server) là một kho lưu trữ cấu trúc dữ liệu in-memory, hoạt động như một database, cache và message broker.

Đặc điểm quan trọng nhất của Redis:

  • In-memory storage: Dữ liệu được lưu trong RAM, nên tốc độ cực nhanh, thường đạt 100,000+ tính toán/giây
  • Persistence: Mặc dù lưu trong RAM, Redis vẫn có thể lưu dữ liệu xuống đĩa để đảm bảo dữ liệu không bị mất khi khởi động lại
  • Đa dạng cấu trúc dữ liệu: Không chỉ có key-value đơn giản mà còn hỗ trợ Lists, Sets, Sorted Sets, Hashes, Streams,...

Các trường hợp sử dụng Redis

"Đừng dùng Redis như một cái búa và coi mọi vấn đề như cái đinh 😁"
  • Caching: Lưu cache để tăng tốc ứng dụng
  • Session storage: Lưu trữ phiên người dùng
  • Real-time analytics: Phân tích dữ liệu thời gian thực
  • Queues: Hàng đợi xử lý task
  • Leaderboards/Counting: Bảng xếp hạng, đếm số lượng
  • Pub/Sub messaging: Messaging giữa các components

Không dùng Redis khi:

  1. Cần lưu trữ dữ liệu quan hệ phức tạp
  2. Dữ liệu quá lớn so với bộ nhớ có sẵn
  3. Cần ACID transactions đầy đủ
  4. Không có kế hoạch quản lý bộ nhớ và persistence

Một số cấu trúc dữ liệu quan trọng trong Redis

Cấu trúc Khi nào nên dùng Lệnh cơ bản
Strings Lưu giá trị đơn giản, counters GET, SET, INCR
Lists Queue, stack, recent items LPUSH, RPUSH, LPOP, LRANGE
Sets Unique collections, relations SADD, SMEMBERS, SINTER
Sorted Sets Ranking, score-based data ZADD, ZRANGE, ZRANK
Hashes Lưu objects với nhiều fields HSET, HGET, HGETALL

II. Tích hợp Redis với FastAPI

Cài đặt Redis

# Cài đặt Redis (Linux/Mac)
# Ubuntu/Debian
sudo apt-get install redis-server # macOS với Homebrew
brew install redis # Cài đặt các thư viện Python
pip install fastapi uvicorn redis jinja2

Nếu sử dụng Windows, bạn có thể tải Redis từ https://github.com/tporadowski/redis/releases hoặc sử dụng Docker.

Mô hình kết nối cơ bản

Tạo file main.py

import redis
from fastapi import FastAPI app = FastAPI() # Kết nối tới Redis
r = redis.Redis( host='localhost', port=6379, # host và port: Địa chỉ của Redis server db=0, decode_responses=True # tự động chuyển bytes sang string
) @app.get("/items/{item_id}")
async def read_item(item_id: str): # Đọc từ Redis item = r.get(f"item:{item_id}") if item is None: # Không tìm thấy trong Redis return {"error": "Item not found"} return {"item": item}

Chạy server: python main.py

Xử lý exception:

# Cách làm sai:
value = r.get("key") # Cách làm đúng:
try: value = r.get("key")
except redis.RedisError as e: log.error(f"Redis error: {e}") # Xử lý fallback

Các pattern phổ biến khi dùng Redis với FastAPI

a. Caching API results

@app.get("/products/{product_id}")
async def get_product(product_id: int): # Thử lấy từ cache cache_key = f"product:{product_id}" cached_data = r.get(cache_key) if cached_data: return json.loads(cached_data) # Nếu không có trong cache, query database product = db.query(Product).filter(Product.id == product_id).first() if product: # Cache kết quả với TTL 1 giờ r.setex(cache_key, 3600, json.dumps(product.dict())) return product return {"error": "Product not found"}

b. Rate limiting

@app.get("/api/data")
async def get_data(request: Request): client_ip = request.client.host key = f"rate:limit:{client_ip}" # Increment counter current = r.incr(key) # Set expiry if this is the first request if current == 1: r.expire(key, 60) # 60 seconds window # Check if rate limit exceeded if current > 10: # Max 10 requests per minute return {"error": "Rate limit exceeded"} # Process request normally return {"data": "Here's your data!"}

c. Session storage

from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer @app.post("/login")
async def login(form_data: OAuth2PasswordRequestForm = Depends()): user = authenticate_user(form_data.username, form_data.password) if not user: raise HTTPException(status_code=401, detail="Invalid credentials") session_id = str(uuid.uuid4()) # Lưu session vào Redis với TTL 1 giờ r.setex(f"session:{session_id}", 3600, json.dumps({"user_id": user.id})) return {"access_token": session_id} async def get_current_user(token: str = Depends(oauth2_scheme)): session_data = r.get(f"session:{token}") if not session_data: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid or expired token", ) user_data = json.loads(session_data) user = get_user(user_data["user_id"]) if not user: raise HTTPException(status_code=404, detail="User not found") return user

III. Lưu ý quan trọng khi dùng Redis

1. Bảo mật Redis

Redis mặc định không có authentication và có thể truy cập từ mọi nơi nếu không được cấu hình đúng:

Các biện pháp bảo mật:

  • Đặt mật khẩu: requirepass trong redis.conf
  • Bind địa chỉ IP cụ thể: bind 127.0.0.1
  • Sử dụng Redis trong mạng riêng
  • Sử dụng TLS cho kết nối từ xa
  • Vô hiệu hóa các lệnh nguy hiểm: rename-command FLUSHALL ""

2. Quản lý bộ nhớ

Redis là in-memory nên việc quản lý bộ nhớ rất quan trọng:

"Đừng lưu những thứ không cần thiết vào Redis. RAM là tài nguyên quý giá."
  • Cài đặt maxmemory và policy: volatile-lru, allkeys-lru
  • Sử dụng TTL (EXPIRE) cho các key khi có thể
  • Giám sát bộ nhớ sử dụng: INFO memory
  • Sử dụng các lệnh tiết kiệm bộ nhớ như HSCAN, SSCAN thay vì HGETALL, SMEMBERS cho dữ liệu lớn

3. Hiệu suất

  • Sử dụng pipeline để giảm độ trễ mạng:
pipe = r.pipeline()
pipe.set("key1", "value1")
pipe.set("key2", "value2")
pipe.set("key3", "value3")
pipe.execute() # Gửi 3 lệnh trong 1 lần round-trip
  • Sử dụng các lệnh atomic: INCR thay vì GET + SET
  • Xem xét sử dụng Redis Cluster cho khả năng mở rộng

IV. Tổng kết

"Redis là công cụ mạnh mẽ, nhưng như mọi công cụ, việc biết khi nào sử dụng nó quan trọng hơn việc biết cách sử dụng nó." Để làm quen có thể bắt đầu với dự án đơn giản tạo ứng dụng học tiếng Anh: https://github.com/hasonsk/redis-fastapi-example

Tài liệu tham khảo

Bình luận

Bài viết tương tự

- vừa được xem lúc

Caching đại pháp 2: Cache thế nào cho hợp lý?

Caching rất dễ. Mình không nói đùa đâu, caching rất là dễ. Ai cũng có thể làm được chỉ sau 10 phút đọc tutorial. Nó cũng giống như việc đứa trẻ lên 3 đã có thể cầm bút để vẽ vậy.

0 0 134

- vừa được xem lúc

Caching đại pháp 1: Nấc thang lên level của developer

Bí quyết thành công trong việc đáp ứng hệ thống triệu user của những công ty lớn (và cả công ty nhỏ). Tại sao caching lại là kỹ thuật tối quan trọng để phù phép ứng dụng rùa bò của chúng ta thành siêu phẩm vạn người mê.

0 0 88

- vừa được xem lúc

Cache dữ liệu Nodejs với Redis

Một tí gọi là lý thuyết để anh em tham khảo. Cache là gì. Lợi ích của việc cache data. .

0 0 122

- vừa được xem lúc

Nguyên tắc hoạt động của redis server

Sự ra đời của Redis. . Câu chuyện bắt đầu khi tác giả của Redis, Salvatore Sanfilippo. (nickname: antirez), cố gắng làm những công việc gần như là không.

0 0 103

- vừa được xem lúc

Viết ứng dụng chat realtime với Laravel, VueJS, Redis và Socket.IO, Laravel Echo

Xin chào tất cả các bạn, đây là một trong những bài post đầu tiên của mình. Sau bao năm toàn đi đọc các blog tích luỹ được chút kiến thức của các cao nhân trên mạng.

0 0 921

- vừa được xem lúc

Tìm hiểu tổng quan về Redis

1. Lời mở đầu.

0 0 378