0Pricing
Redis Caching & Messaging (Pub/Sub, Streams) · درس

الأقفال الموزّعة باستخدام Redis

طبّقوا آليات موثوقة للقفل الموزّع باستخدام Redis لتنسيق الوصول في الأنظمة المتزامنة.

الأقفال الموزّعة باستخدام Redis درس مجاني في Redis Caching & Messaging (Pub/Sub, Streams) على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Redis Caching & Messaging (Pub/Sub, Streams)، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Redis Caching & Messaging (Pub/Sub, Streams) 4 دروس في المجموع.

بعض أجزاء هذا الدرس لم تُترجم بعد وتظهر باللغة الإنجليزية.

The Need for Distributed Locks

Imagine multiple applications or services trying to update the same piece of data, like a user's balance or a unique order ID. Without coordination, they could overwrite each other's changes, leading to data corruption or incorrect states.

  • Race conditions: When operations depend on specific timing, leading to unpredictable results.
  • Data integrity: Ensuring shared resources remain consistent.
  • Concurrency control: Managing access when multiple processes run simultaneously.

Distributed locks are like a single key to a shared room. Only one process can hold the key (lock) at a time, ensuring exclusive access.

Why Redis for Distributed Locks?

Redis is an excellent choice for implementing distributed locks due to its speed, atomic operations, and single-threaded nature.

  • Atomicity: Redis commands are executed atomically, meaning they complete entirely or not at all, preventing partial updates.
  • Performance: In-memory operations ensure very low latency for lock acquisition and release.
  • Simplicity: Basic string commands can be leveraged effectively for locking.

These features allow Redis to manage lock states reliably and efficiently across many different application instances.

Basic Lock Acquisition (SET NX EX)

The core of a Redis-based lock lies in the SET command with specific options:

  • NX (Not eXists): Ensures the key is only set if it doesn't already exist. This is how we acquire the lock exclusively.
  • EX (EXpire): Sets an expiration time for the key in seconds. This is crucial to prevent deadlocks if a client crashes before releasing the lock.
  • value: A unique identifier for the lock holder (e.g., a UUID). This allows only the original lock holder to release it.

The command looks like this: SET mylock:resource <unique_id> NX EX 30

Acquiring a Lock: Code Example

Here's a simplified example of how a client might attempt to acquire a lock using Python. The SET command returns True (or 'OK') if the lock was acquired, and False (or None) otherwise.

import redis
import uuid

# Connect to Redis
r = redis.Redis(decode_responses=True)

lock_key = "resource:123:lock"
client_id = str(uuid.uuid4())
lock_timeout_seconds = 10

print(f"Client {client_id} attempting to acquire lock...")

# Attempt to acquire the lock
# set(name, value, nx=True, ex=timeout) maps to SET key value NX EX timeout
lock_acquired = r.set(lock_key, client_id, nx=True, ex=lock_timeout_seconds)

if lock_acquired:
  print(f"Client {client_id} acquired the lock!")
  # Simulate work
  # time.sleep(5)
  # ... do critical section work ...
  # r.delete(lock_key) # DON'T do this directly!
else:
  print(f"Client {client_id} failed to acquire the lock. It's held by someone else.")

# In a real app, you'd release the lock safely later.

The Challenge of Releasing a Lock Safely

Simply deleting the lock key (e.g., DEL mylock:resource) is NOT safe. Consider this scenario:

  1. Client A acquires the lock with an expiration of 10 seconds.
  2. Client A's operation takes longer than 10 seconds, so the lock expires automatically.
  3. Client B acquires the lock for the same resource.
  4. Client A's operation finally finishes and attempts to delete the lock. It unknowingly deletes Client B's lock!

This leads to two clients thinking they have the lock simultaneously, defeating its purpose. We need an atomic way to check ownership AND delete.

Atomic Release with Lua Scripts

Redis allows executing Lua scripts atomically. This means the entire script runs as a single, uninterruptible operation on the Redis server, solving our lock release problem.

The Lua script for releasing a lock typically does two things:

  1. It checks if the current lock value matches the unique ID provided by the client attempting to release the lock.
  2. If they match, it deletes the lock key.

This guarantees that only the client who originally acquired the lock (and whose unique ID is still stored) can release it, even if the lock has expired and been re-acquired by another client.

Releasing a Lock: Code Example

Here's how you'd execute a Lua script to safely release a lock. The script ensures that you only delete the lock if you are its rightful owner.

import redis
import uuid

r = redis.Redis(decode_responses=True)

lock_key = "resource:123:lock"
client_id = str(uuid.uuid4())
lock_timeout_seconds = 10

# Assume client_id has previously acquired the lock
# For demonstration, let's manually set it:
r.set(lock_key, client_id, nx=True, ex=lock_timeout_seconds)
print(f"Client {client_id} acquired the lock for demo.")

lua_script = """
  if redis.call('GET', KEYS[1]) == ARGV[1] then
    return redis.call('DEL', KEYS[1])
  else
    return 0
  end
"""

# Execute the Lua script
# KEYS[1] is lock_key, ARGV[1] is client_id
released = r.eval(lua_script, 1, lock_key, client_id)

if released:
  print(f"Client {client_id} successfully released the lock.")
else:
  print(f"Client {client_id} failed to release the lock (not owner or already expired).")

# Check if the key still exists
if r.exists(lock_key):
  print(f"Lock key '{lock_key}' still exists.")
else:
  print(f"Lock key '{lock_key}' does not exist.")

Lock Expiration & Renewal

The EX (expiration) option is vital. It acts as a safety net, ensuring locks are eventually released even if the client crashes or fails to release it. Without expiration, a crashed client could hold a lock indefinitely, causing a permanent deadlock.

  • Too short: If the expiration is too short, long-running tasks might lose their lock prematurely.
  • Too long: If it's too long, deadlocks might persist for an unacceptable duration.

For tasks that might exceed the initial expiration, clients can implement a 'lock renewal' mechanism. This involves periodically checking if they still hold the lock and, if so, extending its expiration time using EXPIRE or PEXPIRE commands.

Redlock: For Higher Guarantees

While a single Redis instance with SET NX EX works for many cases, it has a single point of failure. If that Redis instance goes down, all locks are lost or become unavailable.

The Redlock algorithm addresses this by requiring clients to acquire locks on a majority of independent Redis master instances (e.g., 3 out of 5). This provides higher guarantees:

  • Fault tolerance: If one Redis instance fails, the system can still function.
  • Stronger safety: Reduces the chance of multiple clients acquiring the same lock.

Redlock is more complex to implement but offers a robust solution for critical distributed systems.

Quick Check: Lock Properties

Which of the following are essential properties for a reliable distributed lock using Redis, assuming a single Redis instance?

Recap: Distributed Locks with Redis

In this lesson, we explored how to implement reliable distributed locks using Redis.

  • We learned that SET key value NX EX seconds is the foundation for acquiring a lock atomically.
  • A unique value identifies the lock holder, preventing others from releasing it.
  • Expiration (EX) is vital for preventing permanent deadlocks if a client crashes.
  • Safely releasing a lock requires an atomic check-and-delete operation, typically achieved with Lua scripting.
  • For higher reliability and fault tolerance in multi-instance setups, the Redlock algorithm can be employed.

Understanding these principles is key to building robust and concurrent distributed applications.

الأسئلة الشائعة

هل درس «الأقفال الموزّعة باستخدام Redis» مجاني؟

نعم — نص درس «الأقفال الموزّعة باستخدام Redis» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Redis Caching & Messaging (Pub/Sub, Streams)، انتقل إلى CoddyKit PRO. تتضمن دورة Redis Caching & Messaging (Pub/Sub, Streams) 4 دروس في المجموع.

ماذا ستتعلم في «الأقفال الموزّعة باستخدام Redis»؟

طبّقوا آليات موثوقة للقفل الموزّع باستخدام Redis لتنسيق الوصول في الأنظمة المتزامنة. تتمرن على Redis Caching & Messaging (Pub/Sub, Streams) مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Redis Caching & Messaging (Pub/Sub, Streams)؟

لا تُشترط خبرة سابقة. Redis Caching & Messaging (Pub/Sub, Streams) على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.

كم من الوقت يستغرق درس «الأقفال الموزّعة باستخدام Redis»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Redis Caching & Messaging (Pub/Sub, Streams) هذا؟

نعم. كل درس في Redis Caching & Messaging (Pub/Sub, Streams) يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. الأقفال الموزّعة باستخدام Redis
  2. أنماط انتخاب القائد
  3. Redis كخدمة تنسيق
  4. تحديد معدل الطلبات الموزّع
← العودة إلى Redis Caching & Messaging (Pub/Sub, Streams)