杰瑞科技汇

Python memcached能用UDP吗?

Of course. Using Python with Memcached over UDP is possible, but it comes with a significant trade-off: you lose the atomicity guarantees of the cas (Check-And-Set) command.

Python memcached能用UDP吗?-图1
(图片来源网络,侵删)

Here’s a comprehensive guide covering why you'd use UDP, the limitations, and how to implement it in Python.


Why Use UDP with Memcached?

Memcached's primary protocol is TCP, which is reliable and ordered. UDP, on the other hand, is connectionless, fast, and can be lossy.

The main advantage of using UDP is performance. For certain types of applications, the reduced overhead of UDP can lead to lower latency and higher throughput, especially when dealing with very fast, non-critical, or high-volume reads.

Common Use Cases for UDP Memcached:

Python memcached能用UDP吗?-图2
(图片来源网络,侵删)
  • Caching Read-Heavy, Non-Critical Data: Think of caching parts of a public webpage, user avatars, or analytics data where a slightly stale or missing value is acceptable.
  • High-Traffic Logging or Counters: You might use it as a fast, in-memory aggregator for metrics where losing a few increments is not a disaster.
  • Reducing Latency: When every microsecond counts and the data is ephemeral.

The Critical Disadvantage:

The cas (Check-And-Set) command, which is essential for implementing atomic "get-then-set" operations (like a lock or an increment-and-get), is not available over UDP. The Memcached UDP protocol was designed for simple, single-key operations (get, set, add, replace, delete, incr, decr) without the complex response handling required for cas.


Choosing a Python Library

The most popular Python client for Memcached, pymemcache, fully supports UDP operations. It's a robust, feature-rich, and well-maintained library.

Installation:

Python memcached能用UDP吗?-图3
(图片来源网络,侵删)
pip install pymemcache

Python Code Example: UDP with pymemcache

Here is a complete example demonstrating how to connect to a Memcached server using UDP, perform basic operations, and compare it with a TCP connection.

Prerequisites

You need a running Memcached server. If you don't have one, you can start it with UDP support enabled (it's on by default on port 11211).

# On Linux/macOS
memcached -d -l 127.0.0.1 -p 11211
# On Windows (if installed)
memcached.exe -d runservice -l 127.0.0.1 -p 11211

The Python Script

This script will:

  1. Connect to Memcached using both TCP and UDP.
  2. Set a key using both protocols.
  3. Get the key using both protocols.
  4. Attempt an incr operation.
  5. Demonstrate the failure of cas over UDP.
import time
from pymemcache.client.base import Client
from pymemcache.exceptions import MemcacheError
# --- Configuration ---
MEMCACHED_SERVER = ('127.0.0.1', 11211)
KEY = 'my_udp_key'
VALUE = b'Hello from UDP!'
NEW_VALUE = b'Updated value!'
def run_operations(client, protocol_name):
    """Performs a set of memcached operations using the given client."""
    print(f"\n--- Testing with {protocol_name.upper()} ---")
    # 1. SET operation
    print(f"1. Setting '{KEY}' to '{VALUE.decode()}'...")
    success = client.set(KEY, VALUE)
    print(f"   Set successful: {success}")
    # 2. GET operation
    print(f"2. Getting '{KEY}'...")
    retrieved_value = client.get(KEY)
    print(f"   Retrieved value: {retrieved_value.decode() if retrieved_value else 'Not found'}")
    # 3. REPLACE operation
    print(f"3. Replacing '{KEY}' with '{NEW_VALUE.decode()}'...")
    success = client.replace(KEY, NEW_VALUE)
    print(f"   Replace successful: {success}")
    retrieved_value = client.get(KEY)
    print(f"   Retrieved value after replace: {retrieved_value.decode() if retrieved_value else 'Not found'}")
    # 4. INCR operation
    print("4. Testing INCR operation...")
    # First, set a number
    client.set('counter', 10)
    print(f"   Set 'counter' to 10.")
    # Now increment it
    incremented_value = client.incr('counter', 5)
    print(f"   Incremented 'counter' by 5. New value: {incremented_value}")
    # 5. CAS operation (This will fail over UDP)
    print("5. Testing CAS (Check-And-Set) operation...")
    try:
        # Get the value and its CAS token
        result = client.get(KEY, cas_token=True)
        if result:
            value, cas_token = result
            print(f"   Got '{KEY}' with CAS token: {cas_token}")
            # Now try to set it conditionally
            # This will work over TCP but fail over UDP
            print(f"   Attempting to set '{KEY}' conditionally...")
            success = client.set(KEY, b'CAS worked!', cas=cas_token)
            print(f"   CAS set successful: {success}")
            if success:
                final_value = client.get(KEY)
                print(f"   Final value after CAS: {final_value.decode() if final_value else 'Not found'}")
            else:
                print("   CAS failed (token likely changed or not supported).")
        else:
            print(f"   Could not get '{KEY}' for CAS operation.")
    except MemcacheError as e:
        print(f"   An error occurred during CAS: {e}")
        print("   This is expected when using UDP, as CAS is not supported.")
def main():
    """Main function to run the tests."""
    print("Starting Memcached UDP vs TCP operations...")
    # --- Test with TCP (Default) ---
    # This is the standard, reliable connection.
    try:
        tcp_client = Client(MEMCACHED_SERVER, connect_timeout=2, timeout=2)
        run_operations(tcp_client, "TCP")
    except Exception as e:
        print(f"Could not connect to Memcached via TCP: {e}")
        print("Please ensure Memcached is running on 127.0.0.1:11211")
    # --- Test with UDP ---
    # This connection is faster but less reliable and lacks CAS.
    try:
        # The key is to pass `protocol='udp'` to the Client constructor
        udp_client = Client(MEMCACHED_SERVER, connect_timeout=2, timeout=2, protocol='udp')
        run_operations(udp_client, "UDP")
    except Exception as e:
        print(f"Could not connect to Memcached via UDP: {e}")
if __name__ == "__main__":
    main()

Expected Output

When you run this script, you will see the output for TCP operations succeed, including the cas command. The UDP operations will succeed for set, get, replace, and incr, but the cas operation will fail.

Starting Memcached UDP vs TCP operations...
--- Testing with TCP ---
1. Setting 'my_udp_key' to 'Hello from UDP!'...
   Set successful: True
2. Getting 'my_udp_key'...
   Retrieved value: Hello from UDP!
3. Replacing 'my_udp_key' with 'Updated value!'...
   Replace successful: True
   Retrieved value after replace: Updated value!
4. Testing INCR operation...
   Set 'counter' to 10.
   Incremented 'counter' by 5. New value: 15
5. Testing CAS (Check-And-Set) operation...
   Got 'my_udp_key' with CAS token: 1
   Attempting to set 'my_udp_key' conditionally...
   CAS set successful: True
   Final value after CAS: CAS worked!
--- Testing with UDP ---
1. Setting 'my_udp_key' to 'Hello from UDP!'...
   Set successful: True
2. Getting 'my_udp_key'...
   Retrieved value: Hello from UDP!
3. Replacing 'my_udp_key' with 'Updated value!'...
   Replace successful: True
   Retrieved value after replace: Updated value!
4. Testing INCR operation...
   Set 'counter' to 10.
   Incremented 'counter' by 5. New value: 15
5. Testing CAS (Check-And-Set) operation...
   Got 'my_udp_key' with CAS token: 2
   Attempting to set 'my_udp_key' conditionally...
   CAS failed (token likely changed or not supported).

(Note: The CAS token numbers will vary.)


Important Considerations and Best Practices

  1. Reliability vs. Performance: UDP is "fire-and-forget." You don't know if a command arrived or if a response was received. pymemcache will send the command and assume it worked. This is fine for caching where stale data is okay, but do not use UDP for critical application state.

  2. Packet Size: The Memcached UDP protocol has a limitation.

分享:
扫描分享到社交APP
上一篇
下一篇