Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Redis

รับประกันความแม่นยำในการพยากรณ์อย่างต่อเนื่อง:สถานะคงอยู่ในโมเดลอนุกรมเวลาแบบเทียบเคียงพร้อม Redis

รับประกันความแม่นยำในการพยากรณ์อย่างต่อเนื่อง:สถานะคงอยู่ในโมเดลอนุกรมเวลาแบบเทียบเคียงพร้อม Redis

คุณเคยสร้างแบบจำลองอนุกรมเวลาที่ยอดเยี่ยม ซึ่งสามารถคาดการณ์ยอดขายหรือทำนายราคาหุ้นได้เพียงเพื่อดูความล้มเหลวในโลกแห่งความเป็นจริงหรือไม่? นี่เป็นความหงุดหงิดที่พบบ่อย โมเดลของคุณทำงานได้อย่างสมบูรณ์แบบบนเครื่องของคุณ แต่ทันทีที่คุณปรับใช้มันในคอนเทนเนอร์ Docker ดูเหมือนว่าจะเกิดภาวะความจำเสื่อม มันลืมทุกสิ่งที่รู้เมื่อวานนี้ ทำให้การคาดการณ์สำหรับวันพรุ่งนี้ไร้ประโยชน์

ไม่ต้องกังวล. นี่ไม่น่าจะมีข้อบกพร่องในโมเดลของคุณ มันเป็นข้อขัดแย้งระหว่างวิธีการออกแบบโมเดลอนุกรมเวลาและคอนเทนเนอร์ Docker

โมเดลอนุกรมเวลาล้วนเกี่ยวกับหน่วยความจำ พวกเขาต้องจำอดีตเพื่อทำนายอนาคต แต่คอนเทนเนอร์ Docker ถูกสร้างขึ้นมาให้ไม่มีสถานะและหลงลืม โดยจะล้างหน่วยความจำทุกครั้งที่รีสตาร์ท ความขัดแย้งขั้นพื้นฐานนี้สามารถเปลี่ยนแบบจำลองที่ทรงพลังให้กลายเป็นแบบจำลองที่ไร้ค่าในการผลิตได้

ในบทความนี้ เราจะแก้ไขปัญหานั้น เราจะให้แบบจำลองอนุกรมเวลาของคุณมีหน่วยความจำถาวร คุณจะได้เรียนรู้วิธีสร้างบริการคาดการณ์ที่พร้อมใช้งานจริงซึ่งใช้ Redis เป็นสมองภายนอกและวอลุ่ม Docker เพื่อให้แน่ใจว่าหน่วยความจำจะยังคงอยู่เมื่อรีสตาร์ท เราจะอธิบายตัวอย่างแบบลงมือปฏิบัติจริงทีละขั้นตอน เพื่อให้คุณสามารถเรียนรู้วิธีสร้างระบบที่ทั้งชาญฉลาดและเชื่อถือได้อย่างไม่น่าเชื่อ

สิ่งที่เราจะกล่าวถึง:

  • คู่มือนี้เหมาะสำหรับใคร

  • การทำความเข้าใจปัญหา

    • แล้วแบบจำลองอนุกรมเวลาคืออะไร

    • 1. คอนเทนเนอร์เป็นแบบชั่วคราวโดยการออกแบบ

    • 2. สูญเสียบริบทระหว่างการคาดคะเน

    • 3. จำลองภาวะความจำเสื่อมเมื่อรีสตาร์ท

  • วิธีแก้ปัญหา:การจัดเก็บสถานะภายนอก

  • การนำไปปฏิบัติจริง

    • เริ่มต้นด้วยแนวทางที่เสียหาย

    • วิธีแก้ไขด้วยโวลุ่ม

    • รหัสจัดการกับสถานะอย่างไร

    • ทดสอบจุดสิ้นสุดด้านสุขภาพ

  • แล้วการปรับขนาดล่ะ

    • การปรับขนาดแนวนอนด้วย Redis Cluster

    • ความพร้อมใช้งานสูงด้วย Redis Sentinel

    • ใช้บริการ Redis ที่มีการจัดการ

  • ข้อผิดพลาดทั่วไปที่ควรหลีกเลี่ยง

    • อย่าถือว่าปริมาณทำงาน

    • อย่าละเลยขีดจำกัดหน่วยความจำ Redis

    • อย่าข้ามการตรวจสอบ

  • บทสรุป

คู่มือนี้เหมาะกับใคร

เพื่อให้ได้รับประโยชน์สูงสุดจากบทช่วยสอนนี้ การมีบางสิ่งที่เตรียมไว้จะเป็นประโยชน์ เราจะเจาะลึกลงไปในงานโค้ดและบรรทัดคำสั่ง ดังนั้นการเตรียมการเพียงเล็กน้อยจะช่วยได้มาก

  • เครื่องมือหลักสำหรับโปรเจ็กต์นี้คือ Docker และ Docker Compose ตรวจสอบให้แน่ใจว่าคุณได้ติดตั้งและใช้งานบนคอมพิวเตอร์ของคุณ

  • คุณจะพบว่ามันง่ายกว่าที่จะปฏิบัติตามหากคุณพอใจกับพื้นฐานของ Docker, Python และเฟรมเวิร์กเว็บ Flask ประสบการณ์บรรทัดคำสั่งเล็กน้อยจะเป็นประโยชน์สำหรับการรันคำสั่งในบทช่วยสอน

  • แต่ไม่ต้องกังวลหากคุณไม่เคยใช้ Redis มาก่อน สิ่งที่คุณต้องรู้ก็คือมันเป็นฐานข้อมูลในหน่วยความจำที่รวดเร็ว เราจะจัดการส่วนที่เหลือไปพร้อมกัน

คิดว่านี่เป็นไกด์นำเที่ยว ตราบใดที่คุณสงสัยและมีเครื่องมือพื้นฐานพร้อม คุณจะมีรูปร่างที่ดี

การทำความเข้าใจปัญหา

ก่อนที่จะพูดถึงวิธีแก้ปัญหา ก่อนอื่นมาทำความเข้าใจให้ชัดเจนก่อนว่าแบบจำลองอนุกรมเวลาคืออะไร จากนั้นจึงสำรวจว่าทำไมการจัดคอนเทนเนอร์จึงยุ่งยากมาก

แล้วแบบจำลองอนุกรมเวลาคืออะไร

พูดง่ายๆ ก็คือ แบบจำลองอนุกรมเวลาคือแบบจำลองประเภทหนึ่งที่วิเคราะห์จุดข้อมูลที่รวบรวมในช่วงเวลาหนึ่งเพื่อทำนายค่าในอนาคต คิดว่ามันเหมือนกับการพยากรณ์อากาศ นักอุตุนิยมวิทยาไม่ได้มองแค่ท้องฟ้าในขณะนี้ โดยจะพิจารณาอุณหภูมิ ความกดอากาศ และรูปแบบลมจากสองสามชั่วโมงและวันที่ผ่านมาเพื่อคาดการณ์ว่าจะเกิดอะไรขึ้นในวันพรุ่งนี้

แบบจำลองอนุกรมเวลาทำสิ่งเดียวกันกับข้อมูล ไม่ว่าจะเป็นการเข้าชมเว็บไซต์ ราคาหุ้น หรือการใช้พลังงาน ประเด็นสำคัญก็คือประวัติศาสตร์มีความสำคัญ ลำดับของเหตุการณ์ในอดีตให้บริบทที่จำเป็นในการทำนายอนาคตอย่างชาญฉลาด

ต่อไปนี้คือสิ่งที่จะพังเมื่อคุณใส่โมเดลเหล่านี้ใน Docker

1. คอนเทนเนอร์เป็นแบบชั่วคราวโดยการออกแบบ

คอนเทนเนอร์นักเทียบท่ามีไว้เพื่อให้ไร้สัญชาติ สิ่งนี้ใช้งานได้ดีกับ API ส่วนใหญ่ จุดสิ้นสุดโปรไฟล์ผู้ใช้? ไร้สัญชาติ รูปแบบการวิเคราะห์ความรู้สึก? ไร้สัญชาติ พวกเขารับอินพุต ส่งคืนเอาต์พุต และลืมทุกสิ่งที่อยู่ระหว่างนั้น

โมเดลอนุกรมเวลาไม่ทำงานในลักษณะนี้ พวกเขาต้องการบริบทจากการคาดการณ์ครั้งก่อน หากไม่มีสิ่งนี้ โมเดลของคุณก็จะตาบอด

2. สูญเสียบริบทระหว่างการคาดการณ์

การทำนายแต่ละครั้งเกิดขึ้นอย่างแยกจากกัน โมเดลของคุณได้รับจุดข้อมูลจุดเดียวและทำการเดาโดยไม่รู้ว่าอะไรเกิดขึ้นก่อนหน้านี้ สิ่งนี้ทำลายจุดประสงค์ทั้งหมดของการสร้างแบบจำลองอนุกรมเวลา

คุณอาจคิดว่า:"ฉันจะโหลดข้อมูลประวัติทั้งหมดในทุกคำขอ" แต่แนวทางนั้นล้มเหลวด้วยเหตุผลสองประการ:

  • มันช้า. ช้ามากถ้าคุณมีจุดข้อมูลนับพัน

  • มันไม่ปรับขนาด เมื่อคุณมีซีรีส์หลายชุดหรือมีปริมาณคำขอสูง คุณจะไปถึงขีดจำกัดด้านประสิทธิภาพอย่างรวดเร็ว

3. ความจำเสื่อมแบบจำลองเมื่อรีสตาร์ท

ทุกครั้งที่คุณปรับใช้เวอร์ชันใหม่หรือคอนเทนเนอร์ล่ม สถานะสะสมทั้งหมดจะหายไป โมเดลของคุณเริ่มต้นจากศูนย์ ในการผลิต สิ่งนี้เป็นสิ่งที่ยอมรับไม่ได้

วิธีแก้ปัญหา:การจัดเก็บสถานะภายนอก

แทนที่จะรักษาสถานะไว้ในคอนเทนเนอร์ เราจะย้ายมันออกไปข้างนอก Redis กลายเป็นหน่วยความจำของโมเดล

รูปแบบมีลักษณะดังนี้:

Client Request → Flask API → Redis → Prediction with Context

คอนเทนเนอร์ของคุณไม่มีสถานะและสามารถเปลี่ยนได้ แต่ระบบโดยรวมจะรักษาสถานะผ่าน Redis

การใช้งานจริง

มาสร้างสิ่งนี้กันเถอะ โคลนพื้นที่เก็บข้อมูลสาธิต:

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

เริ่มต้นด้วยแนวทางที่แตกหัก

04 ไฟล์แสดงสิ่งที่ไม่ควรทำ:

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

สังเกตว่ามีอะไรหายไป? ไม่มีเล่ม Redis เก็บข้อมูลไว้ในระบบไฟล์ของคอนเทนเนอร์ ซึ่งหมายความว่าข้อมูลนั้นเป็นข้อมูลชั่วคราว

เรียกใช้:

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

ทำนายเล็กน้อย:

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}
 ]
 }'

คุณจะได้รับคำตอบว่า Redis ใช้งานได้:

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

ตอนนี้เริ่มบริการใหม่:

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

ทำนายกันอีก ตรวจสอบ 17 สนาม มันรีเซ็ต ข้อมูลประวัติทั้งหมดของคุณหายไป นี่คือสิ่งที่เราพยายามหลีกเลี่ยง

วิธีแก้ไขด้วยวอลุ่ม

25 ที่ถูกต้อง เพิ่มความคงอยู่:

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:

แล้ว Volume คืออะไรและทำงานอย่างไร

คิดว่าไดรฟ์ข้อมูล Docker เป็นฮาร์ดไดรฟ์ภายนอกเฉพาะสำหรับคอนเทนเนอร์ของคุณ ตามค่าเริ่มต้น เมื่อคอนเทนเนอร์เขียนข้อมูล จะทำเช่นนั้นกับเลเยอร์ชั่วคราวที่จะถูกทำลายเมื่อคอนเทนเนอร์ถูกลบออก โวลุ่มเป็นวิธีหนึ่งในการบันทึกข้อมูลนั้นอย่างถาวร

นี่คือวิธีการทำงาน:

  1. Docker สร้างและจัดการพื้นที่จัดเก็บข้อมูลพิเศษบนเครื่องโฮสต์ ซึ่งแยกออกจากระบบไฟล์ของคอนเทนเนอร์โดยสิ้นเชิง ใน docker-compose.yml ของเรา 36 ส่วนที่ด้านล่างจะบอก Docker ให้สร้างโวลุ่มที่มีชื่อชื่อว่า 41 .

  2. เมื่อคอนเทนเนอร์ Redis เริ่มต้น 58 line บอกให้ Docker "เสียบปลั๊ก" ฮาร์ดไดรฟ์ภายนอกนี้ เชื่อมต่อ 68 เพิ่มระดับเสียงเป็น 77 ไดเร็กทอรีภายในคอนเทนเนอร์

  3. ตอนนี้เมื่อใดก็ตามที่กระบวนการ Redis ภายในคอนเทนเนอร์จะเขียนข้อมูลไปที่ 80 ไดเร็กทอรี (ซึ่งเราได้กำหนดค่าให้ทำ) จริงๆ แล้วเขียนไปที่ 90 ระดับเสียงบนเครื่องโฮสต์

  4. เมื่อคุณเรียกใช้ docker compose down คอนเทนเนอร์ Redis จะถูกทำลาย แต่ 104 ปริมาณไม่ถูกแตะต้อง เหมือนกับการถอดปลั๊กฮาร์ดไดรฟ์ภายนอก และข้อมูลยังคงปลอดภัย ครั้งถัดไปที่คุณเรียกใช้ docker compose up คอนเทนเนอร์ Redis ใหม่จะถูกสร้างขึ้น ไดรฟ์ข้อมูลจะถูกแนบอีกครั้ง และ Redis จะค้นหาข้อมูลเก่าทั้งหมดจากตำแหน่งที่ทิ้งไว้

กลไกนี้เป็นกุญแจสำคัญในการมอบบริการเก็บสถานะของเราด้วยหน่วยความจำที่สามารถรีสตาร์ทได้

เรียกใช้เวอร์ชันที่แก้ไขแล้ว:

docker compose up --build

ส่งคำทำนายหลายประการเพื่อสร้างสถานะ:

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

ตอนนี้มาถึงการทดสอบ รีสตาร์ททุกอย่าง:

docker compose down
docker compose up

ทำนายกันอีก ดูที่ 118 . รวมถึงประเด็นก่อนหน้าทั้งหมด โมเดลจะดำเนินการต่อจากจุดที่ค้างไว้

วิธีนี้ได้ผลเนื่องจากไดรฟ์ข้อมูลมีอยู่อย่างเป็นอิสระจากวงจรการใช้งานคอนเทนเนอร์

โค้ดจัดการกับสถานะอย่างไร

Flask API ใน 123 เก็บแต่ละจุดข้อมูลใน Redis โดยใช้ชุดที่เรียงลำดับ:

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

เมื่อทำการทำนาย ระบบจะดึงข้อมูลประวัติล่าสุด:

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]

ชุดเรียงลำดับ Redis ช่วยให้คุณเรียงลำดับเวลาอัตโนมัติ วอลุ่มช่วยให้มั่นใจได้ว่าข้อมูลนี้จะยังคงอยู่เมื่อรีสตาร์ท

ทดสอบจุดสิ้นสุดด้านสุขภาพ

ตรวจสอบว่าทุกอย่างเชื่อมต่ออย่างถูกต้อง:

curl http://localhost:5000/health

คุณควรเห็น:

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

ถ้า 134 เป็นเท็จ โปรดตรวจสอบบันทึกนักเทียบท่าของคุณ ปัญหาทั่วไปคือการกำหนดค่าเครือข่ายหรือ Redis เริ่มทำงานไม่ถูกต้อง

แล้วการปรับขนาดล่ะ

การตั้งค่านี้ทำงานได้ดีสำหรับการปรับใช้อินสแตนซ์เดียว เมื่อการเข้าชมเพิ่มขึ้น คุณมีทางเลือกสองสามทาง

การปรับสเกลแนวนอนด้วย Redis Cluster

เพื่อให้มีปริมาณงานสูง ให้กระจายข้อมูลของคุณไปยังโหนด Redis หลายโหนด Redis Cluster จัดการการแบ่งส่วนโดยอัตโนมัติ

ความพร้อมใช้งานสูงด้วย Redis Sentinel

เพิ่มความสามารถในการเฟลโอเวอร์เพื่อให้ที่จัดเก็บสถานะของคุณไม่กลายเป็นจุดล้มเหลวเพียงจุดเดียว Sentinel ตรวจสอบอินสแตนซ์ Redis และส่งเสริมการจำลองเมื่ออินสแตนซ์หลักล้มเหลว

ใช้บริการ Redis ที่มีการจัดการ

AWS ElastiCache, Azure Cache สำหรับ Redis หรือ Google Cloud Memorystore จัดการภาระการปฏิบัติงาน คุณมุ่งเน้นไปที่โมเดลของคุณ เพราะโมเดลจะจัดการกับความน่าเชื่อถือของ Redis

ข้อมูลเชิงลึกที่สำคัญ:คอนเทนเนอร์ API ของคุณยังคงไร้สถานะ คุณปรับขนาดร้านค้าของรัฐได้อย่างอิสระ

ข้อผิดพลาดทั่วไปที่ควรหลีกเลี่ยง

ฉันไม่สามารถเน้นย้ำสิ่งนี้ได้เพียงพอ:ทดสอบความเพียรของคุณก่อนปรับใช้กับการใช้งานจริง

อย่าถือว่าปริมาณทำงาน

รีสตาร์ทคอนเทนเนอร์ของคุณจริง ๆ และตรวจสอบว่าสถานะยังคงมีอยู่ ฉันพบว่าการปรับใช้งานล้มเหลวเนื่องจากมีผู้ลืมติดตั้งวอลลุมในการผลิต

อย่าละเลยขีดจำกัดหน่วยความจำ Redis

Redis เก็บทุกสิ่งไว้ในความทรงจำ ตรวจสอบการใช้หน่วยความจำของคุณ ตั้งค่านโยบาย maxmemory ให้เหมาะสมกับภาระงานของคุณ หากหน่วยความจำไม่เพียงพอ Redis จะเริ่มถอดคีย์ออกหรือปฏิเสธการเขียน

อย่าข้ามการตรวจสอบ

เพิ่มการตรวจสุขภาพ ตรวจสอบสถานะการเชื่อมต่อ Redis ติดตามเวลาแฝงของการคาดการณ์ คุณต้องการทราบเมื่อสิ่งต่างๆ พัง ไม่ใช่เรียนรู้จากผู้ใช้ที่โกรธแค้น

บทสรุป

โมเดลอนุกรมเวลาจำเป็นต้องมีหน่วยความจำ คอนเทนเนอร์นักเทียบท่าสูญเสียหน่วยความจำตามค่าเริ่มต้น วิธีแก้ปัญหานั้นง่ายมาก:แยกสถานะออกจากการคำนวณ

ใช้ Redis เป็นที่เก็บสถานะภายนอก ใช้โวลุ่มนักเทียบท่าเพื่อคงสถานะนั้นไว้ โมเดลของคุณยังคงชาญฉลาด คอนเทนเนอร์ของคุณสามารถเปลี่ยนได้ และการปรับใช้ของคุณก็จะเชื่อถือได้

รหัสการทำงานแบบเต็มมีอยู่ที่ github.com/ag-chirag/docker-redis-time-series โคลนมัน รันมัน ทำลายมัน เรียนรู้จากมัน

และจำไว้ว่า:วิธีแก้ปัญหาที่ง่ายที่สุดที่ได้ผลมักจะเป็นวิธีที่ถูกต้อง คุณไม่จำเป็นต้องใช้ Kubernetes และ StatefulSets เสมอไป บางครั้ง Docker Compose และโวลุ่มก็เพียงพอแล้ว

เรียนรู้การเขียนโค้ดฟรี หลักสูตรโอเพ่นซอร์สของ freeCodeCamp ช่วยให้ผู้คนมากกว่า 40,000 คนได้งานในตำแหน่งนักพัฒนา เริ่มต้น