Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Redis

Đảm bảo độ chính xác của dự báo liên tục:Trạng thái bền vững trong các mô hình chuỗi thời gian được Docker hóa với Redis

Đảm bảo độ chính xác của dự báo liên tục:Trạng thái bền vững trong các mô hình chuỗi thời gian được Docker hóa với Redis

Bạn đã bao giờ xây dựng một mô hình chuỗi thời gian tuyệt vời, một mô hình có thể dự báo doanh thu hoặc dự đoán giá cổ phiếu, chỉ để chứng kiến nó thất bại trong thế giới thực chưa? Vâng, đây là một sự thất vọng phổ biến. Mô hình của bạn hoạt động hoàn hảo trên máy của bạn, nhưng thời điểm bạn triển khai nó trong vùng chứa Docker, nó dường như bị mất trí nhớ. Nó quên tất cả những gì nó biết ngày hôm qua, khiến những dự đoán về ngày mai trở nên vô ích.

Đừng lo lắng. Đây có thể không phải là một lỗ hổng trong mô hình của bạn. Đó là sự xung đột giữa cách các mô hình chuỗi thời gian và vùng chứa Docker được thiết kế để hoạt động.

Các mô hình chuỗi thời gian đều liên quan đến bộ nhớ. Họ cần nhớ lại quá khứ để dự đoán tương lai. Nhưng các vùng chứa Docker được xây dựng để không trạng thái và dễ quên, xóa sạch bộ nhớ sau mỗi lần khởi động lại. Xung đột cơ bản này có thể biến một mô hình mạnh mẽ thành một mô hình vô giá trị trong sản xuất.

Trong bài viết này, chúng tôi sẽ giải quyết vấn đề đó. Chúng tôi sẽ cung cấp cho mô hình chuỗi thời gian của bạn một bộ nhớ vĩnh viễn. Bạn sẽ tìm hiểu cách xây dựng một dịch vụ dự đoán sẵn sàng sản xuất sử dụng Redis làm bộ não bên ngoài và các khối Docker để đảm bảo rằng bộ nhớ vẫn tồn tại sau mỗi lần khởi động lại. Chúng tôi sẽ hướng dẫn từng bước một ví dụ thực tế để bạn có thể tìm hiểu cách xây dựng một hệ thống vừa thông minh vừa cực kỳ đáng tin cậy.

Nội dung chúng tôi sẽ đề cập:

  • Hướng dẫn này dành cho ai?

  • Hiểu vấn đề

    • Vậy mô hình chuỗi thời gian là gì?

    • 1. Thiết kế của container là phù du

    • 2. Mất bối cảnh giữa các dự đoán

    • 3. Mất trí nhớ mô hình khi khởi động lại

  • Giải pháp:Lưu trữ trạng thái bên ngoài

  • Triển khai thực tế

    • Bắt đầu với cách tiếp cận bị hỏng

    • Cách khắc phục bằng âm lượng

    • Cách mã xử lý trạng thái

    • Kiểm tra điểm cuối sức khỏe

  • Còn việc mở rộng quy mô thì sao?

    • Chia tỷ lệ theo chiều ngang với Redis Cluster

    • Tính sẵn sàng cao với Redis Sentinel

    • Sử dụng các dịch vụ Redis được quản lý

  • Những cạm bẫy thường gặp cần tránh

    • Đừng cho rằng khối lượng có tác dụng

    • Đừng bỏ qua giới hạn bộ nhớ Redis

    • Đừng bỏ qua việc giám sát

  • Kết luận

Hướng dẫn này dành cho ai?

Để tận dụng tối đa hướng dẫn này, sẽ rất hữu ích nếu bạn chuẩn bị sẵn một số thứ. Chúng ta sẽ đi sâu vào một số mã và công việc dòng lệnh, vì vậy chỉ cần chuẩn bị một chút là bạn sẽ mất nhiều công sức.

  • Các công cụ chính cho dự án này là Docker và Docker Compose. Đảm bảo bạn đã cài đặt và chạy chúng trên máy tính của mình.

  • Bạn cũng sẽ thấy dễ dàng hơn nếu bạn cảm thấy thoải mái với những kiến thức cơ bản về Docker, Python và khung web Flask. Một chút kinh nghiệm về dòng lệnh cũng sẽ hữu ích cho việc chạy các lệnh trong hướng dẫn.

  • Nhưng đừng lo lắng nếu bạn chưa từng sử dụng Redis trước đây. Tất cả những gì bạn cần biết là đó là cơ sở dữ liệu nhanh, trong bộ nhớ. Chúng tôi sẽ xử lý phần còn lại trong quá trình thực hiện.

Hãy coi đây như một chuyến tham quan có hướng dẫn. Chỉ cần bạn tò mò và có sẵn các công cụ cơ bản, bạn sẽ có được vóc dáng tuyệt vời.

Hiểu được vấn đề

Trước khi đi vào giải pháp, trước tiên hãy làm rõ mô hình chuỗi thời gian là gì và sau đó khám phá lý do tại sao việc chứa nó lại khó khăn đến vậy.

Vậy mô hình chuỗi thời gian là gì?

Nói một cách đơn giản, mô hình chuỗi thời gian là một loại mô hình phân tích các điểm dữ liệu được thu thập theo thời gian để dự đoán các giá trị trong tương lai. Hãy nghĩ về nó giống như dự đoán thời tiết. Một nhà khí tượng học không chỉ nhìn vào bầu trời lúc này. Họ xem xét nhiệt độ, áp suất và kiểu gió trong vài giờ và vài ngày qua để dự đoán điều gì sẽ xảy ra vào ngày mai.

Các mô hình chuỗi thời gian thực hiện tương tự với dữ liệu, cho dù đó là lưu lượng truy cập trang web, giá cổ phiếu hay mức tiêu thụ năng lượng. Điểm mấu chốt là lịch sử rất quan trọng. Chuỗi sự kiện trong quá khứ cung cấp bối cảnh cần thiết để đưa ra dự đoán thông minh về tương lai.

Bây giờ, đây là những gì sẽ xảy ra khi bạn đặt các mô hình này vào Docker.

1. Thiết kế của container là phù du

Các container Docker có nghĩa là không trạng thái. Điều này hoạt động tốt với hầu hết các API. Điểm cuối hồ sơ người dùng? Không quốc tịch. Một mô hình phân tích tình cảm? Không quốc tịch. Họ lấy đầu vào, trả lại đầu ra và quên đi mọi thứ ở giữa.

Các mô hình chuỗi thời gian không hoạt động theo cách này. Họ cần bối cảnh từ những dự đoán trước đó. Không có nó, mô hình của bạn về cơ bản sẽ bị mù.

2. Mất bối cảnh giữa các dự đoán

Mỗi dự đoán xảy ra một cách độc lập. Mô hình của bạn nhận được một điểm dữ liệu duy nhất và đưa ra dự đoán mà không cần biết điều gì xảy ra trước đó. Điều này làm mất đi toàn bộ mục đích của việc lập mô hình chuỗi thời gian.

Bạn có thể nghĩ:"Tôi sẽ chỉ tải tất cả dữ liệu lịch sử theo mọi yêu cầu." Nhưng cách tiếp cận đó thất bại vì hai lý do:

  • Nó chậm. Rất chậm nếu bạn có hàng nghìn điểm dữ liệu

  • Nó không có quy mô. Khi bạn có nhiều loạt phim hoặc số lượng yêu cầu cao, bạn sẽ nhanh chóng chạm ngưỡng hiệu suất

3. Mất trí nhớ mô hình khi khởi động lại

Mỗi khi bạn triển khai một phiên bản mới hoặc vùng chứa gặp sự cố, tất cả trạng thái tích lũy sẽ biến mất. Mô hình của bạn bắt đầu từ đầu. Trong sản xuất, điều này là không thể chấp nhận được.

Giải pháp:Lưu trữ trạng thái bên ngoài

Thay vì giữ trạng thái bên trong container, chúng ta sẽ di chuyển nó ra bên ngoài. Redis trở thành bộ nhớ của mô hình.

Mẫu trông như thế này:

Client Request → Flask API → Redis → Prediction with Context

Vùng chứa của bạn không có trạng thái và có thể thay thế được. Nhưng toàn bộ hệ thống vẫn duy trì trạng thái thông qua Redis.

Triển khai thực tế

Hãy xây dựng cái này. Sao chép kho demo:

git clone https://github.com/ag-chirag/docker-redis-time-series
cd docker-redis-time-series

Bắt đầu với cách tiếp cận sai lầm

docker-compose.initial.yml tập tin hiển thị những gì KHÔNG nên làm:

services:
 api:
 build: ./flask-api
 ports:
 - "5000:5000"
 redis:
 image: redis:alpine

Chú ý những gì còn thiếu? Không có tập nào. Redis lưu trữ dữ liệu trong hệ thống tệp của vùng chứa, nghĩa là dữ liệu đó chỉ là tạm thời.

Chạy nó:

docker compose -f docker-compose.initial.yml up

Đưa ra một vài dự đoán:

curl -X POST http://localhost:5000/predict \
 -H "Content-Type: application/json" \
 -d '{
 "series_id": "demo",
 "historical_data": [
 {"timestamp": "2024-01-01T12:00:00", "value": 10},
 {"timestamp": "2024-01-01T12:01:00", "value": 20},
 {"timestamp": "2024-01-01T12:02:00", "value": 30}
 ]
 }'

Bạn sẽ nhận được phản hồi cho biết Redis đang hoạt động:

{
 "data_points_used": 3,
 "prediction": 40,
 "redis_connected": true
}

Bây giờ khởi động lại dịch vụ:

docker compose down
docker compose -f docker-compose.initial.yml up

Đưa ra một dự đoán khác Kiểm tra data_points_used lĩnh vực. Nó thiết lập lại. Tất cả dữ liệu lịch sử của bạn đã biến mất. Đây chính xác là điều chúng tôi đang cố gắng tránh.

Cách khắc phục bằng âm lượng

docker-compose.yml đúng thêm sự kiên trì:

services:
 api:
 build: ./flask-api
 ports:
 - "5000:5000"
 environment:
 - REDIS_HOST=redis
 redis:
 image: redis:alpine
 command: redis-server --appendonly yes
 volumes:
 - redis_data:/data
volumes:
 redis_data:

Vậy, ổ đĩa là gì và nó hoạt động như thế nào?

Hãy coi ổ Docker như một ổ cứng ngoài chuyên dụng cho vùng chứa của bạn. Theo mặc định, khi một vùng chứa ghi dữ liệu, nó sẽ ghi dữ liệu vào một lớp tạm thời và lớp này sẽ bị hủy khi vùng chứa bị xóa. Ổ đĩa cung cấp cách lưu dữ liệu đó vĩnh viễn.

Đây là cách nó hoạt động:

  1. Docker tạo và quản lý một vùng lưu trữ đặc biệt trên máy chủ, tách biệt hoàn toàn với bất kỳ hệ thống tệp nào của vùng chứa. Trong docker-compose.yml của chúng tôi, volumes: redis_data: phần ở phía dưới yêu cầu Docker tạo một tập được đặt tên có tên là redis_data .

  2. Khi vùng chứa Redis khởi động, volumes: - redis_data:/data dòng báo cho Docker "cắm" ổ cứng ngoài này. Nó kết nối redis_data âm lượng đến /data thư mục bên trong container.

  3. Bây giờ, bất cứ khi nào quy trình Redis bên trong vùng chứa ghi dữ liệu vào /data của nó thư mục (mà chúng tôi đã cấu hình để thực hiện), nó thực sự đang ghi vào redis_data âm lượng trên máy chủ.

  4. Khi bạn chạy lệnh soạn thảo docker, vùng chứa Redis sẽ bị hủy, nhưng redis_data âm lượng không bị ảnh hưởng. Nó giống như việc rút ổ cứng ngoài ra mà dữ liệu vẫn được an toàn. Lần tiếp theo khi bạn chạy docker soạn thảo, một vùng chứa Redis hoàn toàn mới sẽ được tạo, ổ đĩa được đính kèm lại và Redis sẽ tìm thấy tất cả dữ liệu cũ ngay tại nơi nó để lại.

Cơ chế này là chìa khóa để cung cấp cho dịch vụ có trạng thái của chúng tôi một bộ nhớ có thể tồn tại sau khi khởi động lại.

Chạy phiên bản đã sửa:

docker compose up --build

Gửi một số dự đoán để xây dựng trạng thái:

for i in {1..5}; do
 curl -X POST http://localhost:5000/predict \
 -H "Content-Type: application/json" \
 -d "{
 \"series_id\": \"demo\",
 \"historical_data\": [{\"timestamp\": \"2024-01-01T12:0$i:00\", \"value\": $((i*10))}]
 }"
done

Bây giờ đến bài kiểm tra. Khởi động lại mọi thứ:

docker compose down
docker compose up

Đưa ra một dự đoán khác Nhìn vào data_points_used . Nó bao gồm tất cả các điểm trước đó. Mô hình tiếp tục chính xác nơi nó đã dừng lại.

Điều này hoạt động vì khối lượng tồn tại độc lập với vòng đời của vùng chứa.

Cách mã xử lý trạng thái

API Flask trong flask-api/app.py lưu trữ từng điểm dữ liệu trong Redis bằng cách sử dụng các bộ được sắp xếp:

def store_data_point(series_id, timestamp, value):
 key = f"ts:{series_id}"
 redis_client.zadd(key, {json.dumps({"ts": timestamp, "val": value}): timestamp})

Khi đưa ra dự đoán, nó sẽ truy xuất lịch sử gần đây:

def get_recent_data(series_id, limit=100):
 key = f"ts:{series_id}"
 data = redis_client.zrange(key, -limit, -1)
 return [json.loads(d) for d in data]

Bộ sắp xếp Redis cung cấp cho bạn thứ tự thời gian tự động. Ổ đĩa đảm bảo dữ liệu này vẫn tồn tại khi khởi động lại.

Kiểm tra điểm cuối tình trạng

Kiểm tra xem mọi thứ đã được kết nối đúng chưa:

curl http://localhost:5000/health

Bạn sẽ thấy:

{
 "model_loaded": true,
 "redis_connected": true,
 "status": "healthy"
}

Nếu redis_connected là sai, hãy kiểm tra nhật ký Docker của bạn. Sự cố thường gặp là cấu hình mạng hoặc Redis không khởi động đúng cách.

Còn việc chia tỷ lệ thì sao?

Thiết lập này hoạt động tốt cho việc triển khai một phiên bản. Khi lưu lượng truy cập tăng lên, bạn có một vài lựa chọn.

Chia tỷ lệ theo chiều ngang với Redis Cluster

Để có thông lượng cao, hãy phân phối dữ liệu của bạn trên nhiều nút Redis. Cụm Redis tự động xử lý phân đoạn.

Tính sẵn sàng cao với Redis Sentinel

Thêm khả năng chuyển đổi dự phòng để kho lưu trữ trạng thái của bạn không trở thành một điểm lỗi duy nhất. Sentinel giám sát các phiên bản Redis và quảng bá các bản sao khi phiên bản chính bị lỗi.

Sử dụng dịch vụ Redis được quản lý

AWS ElastiCache, Azure Cache cho Redis hoặc Google Cloud Memorystore xử lý gánh nặng vận hành. Bạn tập trung vào mô hình của mình, chúng xử lý độ tin cậy của Redis.

Thông tin chi tiết quan trọng:vùng chứa API của bạn vẫn không có trạng thái. Bạn mở rộng quy mô cửa hàng trạng thái một cách độc lập.

Những cạm bẫy thường gặp cần tránh

Tôi không thể nhấn mạnh đủ điều này:hãy kiểm tra tính kiên trì của bạn trước khi triển khai vào sản xuất.

Đừng cho rằng khối lượng sẽ hiệu quả

Trên thực tế, hãy khởi động lại vùng chứa của bạn và xác minh trạng thái vẫn tồn tại. Tôi đã thấy quá trình triển khai không thành công do ai đó quên gắn ổ đĩa vào sản xuất.

Đừng bỏ qua giới hạn bộ nhớ Redis

Redis giữ mọi thứ trong bộ nhớ. Giám sát việc sử dụng bộ nhớ của bạn. Đặt chính sách bộ nhớ tối đa phù hợp với khối lượng công việc của bạn. Nếu bạn hết bộ nhớ, Redis sẽ bắt đầu loại bỏ các phím hoặc từ chối ghi.

Đừng bỏ qua việc giám sát

Thêm kiểm tra sức khỏe. Theo dõi trạng thái kết nối Redis. Theo dõi độ trễ dự đoán. Bạn muốn biết khi nào mọi thứ bị hỏng chứ không phải tìm hiểu về nó từ những người dùng tức giận.

Kết luận

Các mô hình chuỗi thời gian cần bộ nhớ. Bộ chứa Docker bị mất bộ nhớ theo mặc định. Giải pháp rất đơn giản:tách trạng thái khỏi điện toán.

Sử dụng Redis làm cửa hàng trạng thái bên ngoài. Sử dụng khối lượng Docker để duy trì trạng thái đó. Mô hình của bạn luôn thông minh, các thùng chứa của bạn luôn có thể thay thế được và việc triển khai của bạn trở nên đáng tin cậy.

Mã làm việc đầy đủ có sẵn tại github.com/ag-chirag/docker-redis-time-series. Sao chép nó, chạy nó, phá vỡ nó, học hỏi từ nó.

Và hãy nhớ:giải pháp đơn giản nhất có hiệu quả thường là giải pháp phù hợp. Không phải lúc nào bạn cũng cần Kubernetes và StatefulSets. Đôi khi Docker Compose và một ổ đĩa là đủ.

Học cách viết mã miễn phí. Chương trình giảng dạy mã nguồn mở của freeCodeCamp đã giúp hơn 40.000 người có được việc làm với tư cách là nhà phát triển. Bắt đầu