-
Notifications
You must be signed in to change notification settings - Fork 107
Migration Guide redis‐py
This guide provides a comprehensive comparison of how to migrate from redis-py to Valkey Glide, with side-by-side code examples to make the transition as smooth as possible.
pip install valkey-glide
- redis-py offers multiple constructors for different connection configurations
- Glide uses a configuration object that comes pre-configured with best practices
Glide typically requires minimal configuration changes for:
- Timeout settings
- TLS configuration
- Read from replica settings
- User authentication (username & password)
For advanced configurations, refer to the Glide Wiki - Python.
Standalone Mode
redis-py
import redis
# Simple connection
r = redis.Redis(host='localhost', port=6379, db=0)
# With options
r_with_options = redis.Redis(
host='localhost',
port=6379,
username='user',
password='password',
decode_responses=True # Return strings instead of bytes
)
Glide
from glide import GlideClient, GlideClientConfiguration, NodeAddress, ServerCredentials
# Simple connection
addresses = [NodeAddress("localhost", 6379)]
client_config = GlideClientConfiguration(addresses)
client = await GlideClient.create(client_config)
# With options
addresses = [NodeAddress("localhost", 6379)]
client_config = GlideClientConfiguration(
addresses,
use_tls=True,
credentials=ServerCredentials(username="user", password="password"),
read_from=ReadFrom.AZ_AFFINITY,
request_timeout=2000,
connection_backoff=ConnectionBackoffStrategy(
number_of_retries=5,
factor=2,
exponent_base=2,
jitter_percent=10
),
advanced_configuration=AdvancedGlideClientConfiguration(
connection_timeout=5000,
tls_advanced_configuration=TlsAdvancedConfiguration(
use_insecure_tls=False
)
)
)
client_with_options = await GlideClient.create(client_config)
Cluster Mode
redis-py
from redis.cluster import RedisCluster
# Simple connection
rc = RedisCluster(
startup_nodes=[
{"host": "127.0.0.1", "port": 6379},
{"host": "127.0.0.1", "port": 6380}
],
decode_responses=True
)
# With options
rc_with_options = RedisCluster(
startup_nodes=[
{"host": "127.0.0.1", "port": 6379},
{"host": "127.0.0.1", "port": 6380}
],
password="password",
decode_responses=True
)
Glide
from glide import GlideClusterClient, GlideClusterClientConfiguration, NodeAddress, ServerCredentials
# Simple connection
addresses = [
NodeAddress("127.0.0.1", 6379),
NodeAddress("127.0.0.1", 6380)
]
client_config = GlideClusterClientConfiguration(addresses)
client = await GlideClusterClient.create(client_config)
# With options
addresses = [
NodeAddress("127.0.0.1", 6379),
NodeAddress("127.0.0.1", 6380)
]
credentials = ServerCredentials(password="password")
client_config = GlideClusterClientConfiguration(
addresses,
use_tls=True,
credentials=credentials,
read_from=ReadFrom.AZ_AFFINITY,
request_timeout=2000,
connection_backoff=ConnectionBackoffStrategy(
number_of_retries=5,
factor=2,
exponent_base=2,
jitter_percent=10
),
advanced_configuration=AdvancedGlideClusterClientConfiguration(
connection_timeout=5000,
tls_advanced_configuration=TlsAdvancedConfiguration(
use_insecure_tls=False
)
)
)
client_with_options = await GlideClusterClient.create(client_config)
Constructor Parameters Comparison
The table below compares redis-py constructors with Glide configuration parameters:
redis-py Parameter | Equivalent Glide Configuration |
---|---|
host: str |
addresses: [NodeAddress(host="host", port=port)] |
port: int |
addresses: [NodeAddress(host="host", port=port)] |
db: int |
- Use client.select(db) after connection |
username: str |
credentials: ServerCredentials(username="username") |
password: str |
credentials: ServerCredentials(password="password") |
socket_timeout: float |
request_timeout: int (in milliseconds) |
socket_connect_timeout: float |
advanced_configuration: AdvancedGlideClientConfiguration(connection_timeout=timeout) |
decode_responses: bool |
Use .decode() on returned bytes |
retry_on_timeout: bool |
connection_backoff: ConnectionBackoffStrategy(number_of_retries=retries, factor=factor, exponent_base=base, jitter_percent=percent) |
ssl: bool |
use_tls: bool |
client_name: str |
client_name: str |
read_from_replicas: bool |
read_from: ReadFrom.REPLICA / read_from: ReadFrom.PREFER_REPLICA / read_from: ReadFrom.AZ_AFFINITY / read_from: ReadFrom.AZ_AFFINITY_REPLICAS_AND_PRIMARY Read about AZ affinity
|
lazy_connect: bool |
lazy_connect: bool |
Advanced configuration
Standalone Mode uses GlideClientConfiguration
and Cluster Mode uses GlideClusterClientConfiguration
, but the usage is similar:
# Standalone mode
client_config = GlideClientConfiguration(
addresses=[NodeAddress(host="localhost", port=6379)],
request_timeout=500 # 500ms timeout
)
client = await GlideClient.create(client_config)
# Cluster mode
cluster_config = GlideClusterClientConfiguration(
addresses=[NodeAddress(host="localhost", port=6379)],
request_timeout=500 # 500ms timeout
)
cluster_client = await GlideClusterClient.create(cluster_config)
Below is a comprehensive list of common Redis commands and how they are implemented in both redis-py and Glide.
SET & GET
The SET
command stores a key-value pair in Valkey, while GET
retrieves the value associated with a key.
- Both redis-py and Glide support these commands in the same way.
- Note that redis-py can return strings if
decode_responses=True
is set, while Glide always returns bytes.
redis-py
await r.set('key', 'value')
val = await r.get('key') # b"value" or "value" if decode_responses=True
# With options
await r.set('key', 'value', ex=60) # Set with 60 second expiry
Glide
await client.set('key', 'value')
val = await client.get('key') # b"value"
# With options
from glide import ExpiryType
await client.set('key', 'value', expiry=ExpirySet(ExpiryType.SEC, 60))
SETEX (Set with Expiry)
The SETEX
command sets a key with an expiration time in seconds.
- In redis-py, this is a dedicated function.
- In Glide, expiration is handled using the
ExpirySet
class within theset()
command.
redis-py
await r.setex('key', 5, 'value') # Set with 5 second expiry
Glide
from glide import ExpiryType, ExpirySet
await client.set('key', 'value', expiry=ExpirySet(ExpiryType.SEC, 5))
SETNX (Set if Not Exists)
The SETNX
command sets a key only if it does not already exist.
- In redis-py, this is a dedicated function that returns True if the key was set, False if the key already exists.
- In Glide, this is handled using the
ConditionalChange
enum within theset()
command.
redis-py
result = await r.setnx('key', 'value') # Returns True if key was set, False if key exists
Glide
from glide import ConditionalChange
result = await client.set('key', 'value', conditional_set=ConditionalChange.ONLY_IF_DOES_NOT_EXIST)
# Returns "OK" if key was set, None if key exists
MSET & MGET (Multiple Set/Get)
The MSET
command sets multiple key-value pairs in a single operation, while MGET
retrieves values for multiple keys.
- Both redis-py and Glide support these commands in a similar way.
- For
mget()
, both libraries accept a list of keys.
redis-py
# Multiple set
await r.mset({'key1': 'value1', 'key2': 'value2'})
# Multiple get
values = await r.mget(['key1', 'key2']) # [b'value1', b'value2'] or ["value1", "value2"] if decode_responses=True
Glide
# Multiple set
await client.mset({'key1': 'value1', 'key2': 'value2'})
# Multiple get
values = await client.mget(['key1', 'key2']) # [b'value1', b'value2']
INCR & DECR
The INCR
command increments the value of a key by 1, while DECR
decrements it by 1.
- Both redis-py and Glide support these commands in the same way.
- The key must contain an integer value, otherwise an error will be returned.
redis-py
await r.incr('counter') # counter = 1
await r.decr('counter') # counter = 0
Glide
await client.incr('counter') # counter = 1
await client.decr('counter') # counter = 0
INCRBY & DECRBY
The INCRBY
command increases the value of a key by a specified amount, while DECRBY
decreases it by a specified amount.
- Both redis-py and Glide support these commands in the same way.
- The key must contain an integer value, otherwise an error will be returned.
redis-py
await r.incrby('counter', 5) # 5
await r.decrby('counter', 2) # 3
Glide
await client.incrby('counter', 5) # 5
await client.decrby('counter', 2) # 3
APPEND
The APPEND
command appends a value to the end of an existing string stored at a key.
- Both redis-py and Glide support this command in the same way.
- Returns the length of the string after the append operation.
redis-py
await r.set('greeting', 'Hello')
await r.append('greeting', ' World') # Returns length: 11
result = await r.get('greeting') # b"Hello World" or "Hello World" if decode_responses=True
Glide
await client.set('greeting', 'Hello')
await client.append('greeting', ' World') # Returns length: 11
result = await client.get('greeting') # b"Hello World"
GETRANGE & SETRANGE
The GETRANGE
command retrieves a substring from a string value stored at a key, while SETRANGE
overwrites part of a string at a key starting at a specified offset.
- Both redis-py and Glide support these commands in the same way.
- Note that in Glide, the method names are
getrange
andsetrange
(lowercase).
redis-py
await r.set('key', 'Hello World')
result = await r.getrange('key', 0, 4) # b"Hello" or "Hello" if decode_responses=True
await r.setrange('key', 6, 'Redis') # Returns length: 11
updated = await r.get('key') # b"Hello Redis" or "Hello Redis" if decode_responses=True
Glide
await client.set('key', 'Hello World')
result = await client.getrange('key', 0, 4) # b"Hello"
await client.setrange('key', 6, 'Redis') # Returns length: 11
updated = await client.get('key') # b"Hello Redis"
DEL (Delete)
The DEL
command removes one or more keys from Valkey.
- In redis-py,
delete()
accepts multiple keys as separate arguments or as a list. - In Glide,
del()
requires a list of keys.
redis-py
await r.delete('key1', 'key2') # 2 (number of keys deleted)
# or
await r.delete(['key1', 'key2']) # 2 (number of keys deleted)
Glide
await client.delete(['key1', 'key2']) # 2 (number of keys deleted)
EXISTS
The EXISTS
command checks if one or more keys exist in Valkey.
- In redis-py,
exists()
accepts multiple keys as separate arguments or as a list and returns the number of keys that exist. - In Glide,
exists()
requires a list of keys and also returns the number of keys that exist.
redis-py
await r.exists('existKey', 'nonExistKey') # 1 (number of keys that exist)
# or
await r.exists(['existKey', 'nonExistKey']) # 1 (number of keys that exist)
Glide
await client.exists(['existKey', 'nonExistKey']) # 1 (number of keys that exist)
EXPIRE & TTL
The EXPIRE
command sets a time-to-live (TTL) for a key, after which it will be automatically deleted. The TTL
command returns the remaining time-to-live for a key.
- In redis-py,
expire()
returns True if successful, False if the key doesn't exist or couldn't be expired. - In Glide,
expire()
returns True if successful, False otherwise.
redis-py
await r.expire('key', 10) # True (success)
ttl = await r.ttl('key') # 10 (seconds remaining)
Glide
await client.expire('key', 10) # True (success)
ttl = await client.ttl('key') # 10 (seconds remaining)
KEYS & SCAN
The KEYS
command returns all keys matching a pattern, while SCAN
iterates through keys in a more efficient way for production use.
-
KEYS
is not recommended for production use as it blocks the server until completion. -
SCAN
is the preferred method for iterating through keys in production environments. - In Glide, the cursor returned by
scan()
is a bytes object that needs to be converted to a string using.decode()
or.toString()
.
redis-py
# KEYS (not recommended for production)
all_keys = await r.keys('*')
# SCAN (recommended for production)
cursor = '0'
while cursor != 0:
cursor, keys = await r.scan(cursor=cursor, match='*')
if keys:
print(f'SCAN iteration: {", ".join(keys)}')
Glide
# KEYS (not recommended for production)
all_keys = await client.keys('*')
# SCAN (recommended for production)
cursor = '0'
while cursor != '0':
result = await client.scan(cursor)
cursor = result[0].decode() # or result[0].toString()
keys = result[1]
if keys:
print(f'SCAN iteration: {", ".join([k.decode() for k in keys])}')
RENAME & RENAMENX
The RENAME
command renames a key, while RENAMENX
renames a key only if the new key does not already exist.
- In redis-py,
renamenx()
returns True if successful, False if the target key already exists. - In Glide,
renamenx()
returns True if successful, False if the target key already exists.
redis-py
await r.set('oldkey', 'value')
await r.rename('oldkey', 'newkey') # True
await r.set('key1', 'value1')
result = await r.renamenx('key1', 'key2') # True (success)
Glide
await client.set('oldkey', 'value')
await client.rename('oldkey', 'newkey') # "OK"
await client.set('key1', 'value1')
result = await client.renamenx('key1', 'key2') # True (success)
HSET & HGET
The HSET
command sets field-value pairs in a hash stored at a key, while HGET
retrieves the value of a specific field.
- In redis-py,
hset()
can accept field-value pairs as separate arguments or as a mapping. - In Glide,
hset()
accepts a key and a mapping of field-value pairs.
redis-py
# Set a single field
await r.hset('hash', 'key1', '1') # 1 (field added)
# Set multiple fields
await r.hset('hash', mapping={'key1': '1', 'key2': '2'}) # 2 (fields added)
# Get a single field
value = await r.hget('hash', 'key1') # b"1" or "1" if decode_responses=True
Glide
# Set multiple fields
await client.hset('hash', {'key1': '1', 'key2': '2'}) # 2 (fields added)
# Get a single field
value = await client.hget('hash', 'key1') # b"1"
HMSET & HMGET
The HMSET
command sets multiple field-value pairs in a hash, while HMGET
retrieves values for multiple fields.
- In redis-py,
hmset()
accepts a mapping of field-value pairs. - In Glide, there is no separate
hmset()
method; instead,hset()
is used for setting multiple fields. - For
hmget()
, both libraries require a key and a list of fields.
redis-py
# Set multiple fields
await r.hmset('hash', {'key1': '1', 'key2': '2'})
# Get multiple fields
values = await r.hmget('hash', ['key1', 'key2']) # [b"1", b"2"] or ["1", "2"] if decode_responses=True
Glide
# Set multiple fields (same as hset in Glide)
await client.hset('hash', {'key1': '1', 'key2': '2'})
# Get multiple fields
values = await client.hmget('hash', ['key1', 'key2']) # [b"1", b"2"]
HGETALL
The HGETALL
command retrieves all field-value pairs from a hash.
- Both redis-py and Glide support this command in the same way.
- Returns a dictionary with field names as keys and their values.
redis-py
await r.hset('user', mapping={'name': 'John', 'age': '30'})
user = await r.hgetall('user') # {b'name': b'John', b'age': b'30'} or {'name': 'John', 'age': '30'} if decode_responses=True
Glide
await client.hset('user', {'name': 'John', 'age': '30'})
user = await client.hgetall('user') # {b'name': b'John', b'age': b'30'}
HDEL & HEXISTS
The HDEL
command removes one or more fields from a hash, while HEXISTS
checks if a field exists in a hash.
- In redis-py,
hdel()
accepts multiple fields as separate arguments or as a list and returns the number of fields removed. - In Glide,
hdel()
requires a list of fields. - For
hexists()
, both libraries return True if the field exists, False if it doesn't.
redis-py
await r.hset('hash', mapping={'key1': '1', 'key2': '2', 'key3': '3'})
await r.hdel('hash', 'key1', 'key2') # 2 (fields deleted)
# or
await r.hdel('hash', ['key1', 'key2']) # 2 (fields deleted)
exists = await r.hexists('hash', 'key3') # True (exists)
not_exists = await r.hexists('hash', 'key1') # False (doesn't exist)
Glide
await client.hset('hash', {'key1': '1', 'key2': '2', 'key3': '3'})
await client.hdel('hash', ['key1', 'key2']) # 2 (fields deleted)
exists = await client.hexists('hash', 'key3') # True
not_exists = await client.hexists('hash', 'key1') # False
LPUSH & RPUSH
The LPUSH
command adds elements to the beginning of a list, while RPUSH
adds elements to the end of a list.
- In redis-py, these commands accept multiple elements as separate arguments or as a list.
- In Glide, they require a list of elements.
- Both return the length of the list after the operation.
redis-py
length_of_list = await r.lpush('list', 'a', 'b', 'c') # length_of_list = 3
# or
length_of_list = await r.lpush('list', ['a', 'b', 'c']) # length_of_list = 3
length_of_list = await r.rpush('list', 'd', 'e') # length_of_list = 5
# or
length_of_list = await r.rpush('list', ['d', 'e']) # length_of_list = 5
Glide
length_of_list = await client.lpush('list', ['a', 'b', 'c']) # length_of_list = 3
length_of_list = await client.rpush('list', ['d', 'e']) # length_of_list = 5
LPOP & RPOP
The LPOP
command removes and returns the first element of a list, while RPOP
removes and returns the last element.
- Both redis-py and Glide support these commands in the same way.
- Returns None if the list doesn't exist or is empty.
redis-py
await r.rpush('list', ['a', 'b', 'c'])
first = await r.lpop('list') # b"a" or "a" if decode_responses=True
last = await r.rpop('list') # b"c" or "c" if decode_responses=True
Glide
await client.rpush('list', ['a', 'b', 'c'])
first = await client.lpop('list') # b"a"
last = await client.rpop('list') # b"c"
LRANGE
The LRANGE
command retrieves a range of elements from a list.
- Both redis-py and Glide support this command in the same way.
- The range is specified by start and stop indices, where 0 is the first element, -1 is the last element.
redis-py
await r.rpush('list', ['a', 'b', 'c', 'd', 'e'])
elements = await r.lrange('list', 0, 2) # [b"a", b"b", b"c"] or ["a", "b", "c"] if decode_responses=True
Glide
await client.rpush('list', ['a', 'b', 'c', 'd', 'e'])
elements = await client.lrange('list', 0, 2) # [b"a", b"b", b"c"]
SADD & SMEMBERS
The SADD
command adds one or more members to a set, while SMEMBERS
returns all members of a set.
- In redis-py,
sadd()
accepts multiple members as separate arguments or as a list. - In Glide,
sadd()
requires a list of members. - Both return the number of members that were added to the set (excluding members that were already present).
redis-py
await r.sadd('set', 'a', 'b', 'c') # 3 (members added)
# or
await r.sadd('set', ['a', 'b', 'c']) # 3 (members added)
members = await r.smembers('set') # {b"a", b"b", b"c"} or {"a", "b", "c"} if decode_responses=True
Glide
await client.sadd('set', ['a', 'b', 'c']) # 3 (members added)
members = await client.smembers('set') # {b"a", b"b", b"c"}
SREM & SISMEMBER
The SREM
command removes one or more members from a set, while SISMEMBER
checks if a value is a member of a set.
- In redis-py,
srem()
accepts multiple members as separate arguments or as a list and returns the number of members removed. - In Glide,
srem()
requires a list of members. - For
sismember()
, both libraries return True if the member exists, False if it doesn't.
redis-py
await r.sadd('set', ['a', 'b', 'c'])
await r.srem('set', 'a', 'b') # 2 (members removed)
# or
await r.srem('set', ['a', 'b']) # 2 (members removed)
is_member = await r.sismember('set', 'c') # True (is member)
not_member = await r.sismember('set', 'a') # False (not member)
Glide
await client.sadd('set', ['a', 'b', 'c'])
await client.srem('set', ['a', 'b']) # 2 (members removed)
is_member = await client.sismember('set', 'c') # True
not_member = await client.sismember('set', 'a') # False
ZADD & ZRANGE
The ZADD
command adds one or more members with scores to a sorted set, while ZRANGE
retrieves members from a sorted set by index range.
- In redis-py,
zadd()
accepts score-member pairs as separate arguments or as a mapping. - In Glide,
zadd()
requires a list of objects with score and member properties. - For
zrange()
with scores, redis-py uses a 'withscores' parameter, while Glide uses an options object.
redis-py
# Using separate arguments
await r.zadd('sortedSet', {'one': 1, 'two': 2, 'three': 3}) # 3 (members added)
members = await r.zrange('sortedSet', 0, -1) # [b"one", b"two", b"three"] or ["one", "two", "three"] if decode_responses=True
# With scores
with_scores = await r.zrange('sortedSet', 0, -1, withscores=True)
# [(b"one", 1.0), (b"two", 2.0), (b"three", 3.0)] or [("one", 1.0), ("two", 2.0), ("three", 3.0)] if decode_responses=True
Glide
await client.zadd('sortedSet', [
{'score': 1, 'member': 'one'},
{'score': 2, 'member': 'two'},
{'score': 3, 'member': 'three'}
]) # 3 (members added)
members = await client.zrange('sortedSet', 0, -1) # [b"one", b"two", b"three"]
# With scores
with_scores = await client.zrange('sortedSet', 0, -1, with_scores=True)
# [(b"one", 1.0), (b"two", 2.0), (b"three", 3.0)]
ZREM & ZSCORE
The ZREM
command removes one or more members from a sorted set, while ZSCORE
returns the score of a member in a sorted set.
- In redis-py,
zrem()
accepts multiple members as separate arguments or as a list. - In Glide,
zrem()
requires a list of members. - Both return the number of members that were removed from the sorted set.
redis-py
await r.zadd('sortedSet', {'one': 1, 'two': 2, 'three': 3})
await r.zrem('sortedSet', 'one', 'two') # 2 (members removed)
# or
await r.zrem('sortedSet', ['one', 'two']) # 2 (members removed)
score = await r.zscore('sortedSet', 'three') # 3.0
Glide
await client.zadd('sortedSet', [
{'score': 1, 'member': 'one'},
{'score': 2, 'member': 'two'},
{'score': 3, 'member': 'three'}
])
await client.zrem('sortedSet', ['one', 'two']) # 2 (members removed)
score = await client.zscore('sortedSet', 'three') # 3.0
ZRANK & ZREVRANK
The ZRANK
command returns the rank (position) of a member in a sorted set, while ZREVRANK
returns the rank in reverse order.
- Both redis-py and Glide support these commands in the same way.
- Ranks are 0-based, meaning the member with the lowest score has rank 0.
-
ZREVRANK
returns the rank in descending order, where the member with the highest score has rank 0.
redis-py
await r.zadd('sortedSet', {'one': 1, 'two': 2, 'three': 3})
rank = await r.zrank('sortedSet', 'two') # 1 (0-based index)
rev_rank = await r.zrevrank('sortedSet', 'two') # 1 (0-based index from end)
Glide
await client.zadd('sortedSet', [
{'score': 1, 'member': 'one'},
{'score': 2, 'member': 'two'},
{'score': 3, 'member': 'three'}
])
rank = await client.zrank('sortedSet', 'two') # 1 (0-based index)
rev_rank = await client.zrevrank('sortedSet', 'two') # 1 (0-based index from end)
Transactions (MULTI / EXEC)
The MULTI
command starts a transaction block, while EXEC
executes all commands issued after MULTI.
- In redis-py, transactions are created using
r.pipeline(transaction=True)
and executed withexecute()
. - In Glide, transactions are created using the
Transaction
class and executed withclient.exec()
. - The result format is similar: both return a list of results corresponding to each command in the transaction.
redis-py
# Create a transaction
pipeline = r.pipeline(transaction=True)
pipeline.set("key", "value")
pipeline.get("key")
result = await pipeline.execute() # [True, b"value"] or [True, "value"] if decode_responses=True
Glide
from glide import Transaction
# Create a transaction
transaction = Transaction()
transaction.set("key", "value")
transaction.get("key")
result = await client.exec(transaction) # ["OK", b"value"]
EVAL / EVALSHA
The EVAL
command executes a Lua script on the server, while EVALSHA
executes a script cached on the server using its SHA1 hash.
- In redis-py, these commands require specifying the script, the number of keys, and passing keys and arguments separately.
- In Glide, scripts are created using the
Script
class and executed withinvoke_script()
, with keys and arguments passed in separate lists. -
Glide automatically handles script caching, so there's no need for separate
EVALSHA
handling.
redis-py
# EVAL
lua_script = "return {KEYS[1], ARGV[1]}"
result = await r.eval(lua_script, 1, "foo", "bar")
print(result) # [b'foo', b'bar'] or ['foo', 'bar'] if decode_responses=True
# EVALSHA
sha = await r.script_load(lua_script)
sha_result = await r.evalsha(sha, 1, "foo", "bar")
print(sha_result) # [b'foo', b'bar'] or ['foo', 'bar'] if decode_responses=True
Glide
from glide import Script
lua_script = Script("return {KEYS[1], ARGV[1]}")
result = await client.invoke_script(lua_script, keys=["foo"], args=["bar"])
print(result) # [b'foo', b'bar']
AUTH
The AUTH
command authenticates a client connection to the Valkey server.
- In redis-py, authentication is done using the
auth()
method or during client initialization. - In Glide, authentication is handled during client initialization using
ServerCredentials
.
redis-py
# During initialization
r = redis.Redis(host='localhost', port=6379, password='mypass')
# Or after initialization
await r.auth('mypass') # True
Glide
# During initialization
credentials = ServerCredentials(password="mypass")
client_config = GlideClientConfiguration(
addresses=[NodeAddress(host="localhost", port=6379)],
credentials=credentials
)
client = await GlideClient.create(client_config)
Custom Commands
Both libraries provide ways to execute custom or raw Redis commands.
- In redis-py, you can use the
execute_command()
method. - In Glide, you can use the
custom_command()
method.
redis-py
# Execute a raw command
result = await r.execute_command('SET', 'key', 'value')
print(result) # True or "OK" depending on the command
# Another example
result = await r.execute_command('HSET', 'hash', 'field', 'value')
print(result) # 1
Glide
# Execute a raw command
result = await client.custom_command(['SET', 'key', 'value'])
print(result) # "OK"
# Another example
result = await client.custom_command(['HSET', 'hash', 'field', 'value'])
print(result) # 1
Close / Disconnect
Properly closing connections is important to free up resources and avoid connection leaks.
- Both redis-py and Glide provide simple
close()
methods to close connections. - In redis-py, you can also use connection pools which handle connection lifecycle automatically.
redis-py
# Close connection
await r.close()
# For cluster connections
await rc.close()
# Connection pools are closed automatically when the client is closed
Glide
# Close client (works for both standalone and cluster)
await client.close()
Below is a comprehensive chart comparing common Redis commands between redis-py and Valkey Glide:
Command | redis-py | Valkey Glide |
---|---|---|
Connection | ||
Connect | redis.Redis(host='localhost', port=6379) |
GlideClient.create(GlideClientConfiguration(addresses=[NodeAddress(host="localhost", port=6379)])) |
Cluster | RedisCluster(startup_nodes=[{"host": "127.0.0.1", "port": 6379}]) |
GlideClusterClient.create(GlideClusterClientConfiguration(addresses=[NodeAddress(host="127.0.0.1", port=6379)])) |
Auth | r.auth('pass') |
Set in configuration with ServerCredentials
|
Select DB | r.select(1) |
client.select(1) |
Strings | ||
SET | r.set('key', 'val') |
client.set('key', 'val') |
GET | r.get('key') |
client.get('key') |
SETEX | r.setex('key', 10, 'val') |
client.set('key', 'val', expiry=ExpirySet(ExpiryType.SEC, 10)) |
SETNX | r.setnx('key', 'val') |
client.set('key', 'val', conditional_set=ConditionalChange.ONLY_IF_DOES_NOT_EXIST) |
MSET | r.mset({'key1': 'val1'}) |
client.mset({'key1': 'val1'}) |
MGET | r.mget(['key1', 'key2']) |
client.mget(['key1', 'key2']) |
INCR | r.incr('counter') |
client.incr('counter') |
DECR | r.decr('counter') |
client.decr('counter') |
INCRBY | r.incrby('counter', 5) |
client.incrby('counter', 5) |
DECRBY | r.decrby('counter', 5) |
client.decrby('counter', 5) |
APPEND | r.append('key', 'val') |
client.append('key', 'val') |
GETRANGE | r.getrange('key', 0, 3) |
client.getrange('key', 0, 3) |
SETRANGE | r.setrange('key', 0, 'val') |
client.setrange('key', 0, 'val') |
Keys | ||
DEL |
r.delete('key1', 'key2') or r.delete(['key1', 'key2'])
|
client.delete(['key1', 'key2']) |
EXISTS |
r.exists('key1', 'key2') or r.exists(['key1', 'key2'])
|
client.exists(['key1', 'key2']) |
EXPIRE | r.expire('key', 10) |
client.expire('key', 10) |
TTL | r.ttl('key') |
client.ttl('key') |
KEYS | r.keys('pattern') |
client.keys('pattern') |
SCAN | r.scan(cursor=0, match='*') |
client.scan('0') |
RENAME | r.rename('old', 'new') |
client.rename('old', 'new') |
RENAMENX | r.renamenx('old', 'new') |
client.renamenx('old', 'new') |
Hashes | ||
HSET |
r.hset('hash', 'k1', 'v1') or r.hset('hash', mapping={'k1': 'v1'})
|
client.hset('hash', {'k1': 'v1'}) |
HGET | r.hget('hash', 'field') |
client.hget('hash', 'field') |
HMSET | r.hmset('hash', {'k1': 'v1'}) |
client.hset('hash', {'k1': 'v1'}) |
HMGET | r.hmget('hash', ['k1', 'k2']) |
client.hmget('hash', ['k1', 'k2']) |
HGETALL | r.hgetall('hash') |
client.hgetall('hash') |
HDEL |
r.hdel('hash', 'k1', 'k2') or r.hdel('hash', ['k1', 'k2'])
|
client.hdel('hash', ['k1', 'k2']) |
HEXISTS | r.hexists('hash', 'field') |
client.hexists('hash', 'field') |
Lists | ||
LPUSH |
r.lpush('list', 'a', 'b') or r.lpush('list', ['a', 'b'])
|
client.lpush('list', ['a', 'b']) |
RPUSH |
r.rpush('list', 'a', 'b') or r.rpush('list', ['a', 'b'])
|
client.rpush('list', ['a', 'b']) |
LPOP | r.lpop('list') |
client.lpop('list') |
RPOP | r.rpop('list') |
client.rpop('list') |
LRANGE | r.lrange('list', 0, -1) |
client.lrange('list', 0, -1) |
Sets | ||
SADD |
r.sadd('set', 'a', 'b') or r.sadd('set', ['a', 'b'])
|
client.sadd('set', ['a', 'b']) |
SMEMBERS | r.smembers('set') |
client.smembers('set') |
SREM |
r.srem('set', 'a', 'b') or r.srem('set', ['a', 'b'])
|
client.srem('set', ['a', 'b']) |
SISMEMBER | r.sismember('set', 'a') |
client.sismember('set', 'a') |
Sorted Sets | ||
ZADD | r.zadd('zset', {'a': 1, 'b': 2}) |
client.zadd('zset', [{'score': 1, 'member': 'a'}, {'score': 2, 'member': 'b'}]) |
ZRANGE | r.zrange('zset', 0, -1) |
client.zrange('zset', 0, -1) |
ZRANGE with scores | r.zrange('zset', 0, -1, withscores=True) |
client.zrange('zset', 0, -1, with_scores=True) |
ZREM |
r.zrem('zset', 'a', 'b') or r.zrem('zset', ['a', 'b'])
|
client.zrem('zset', ['a', 'b']) |
ZSCORE | r.zscore('zset', 'a') |
client.zscore('zset', 'a') |
ZRANK | r.zrank('zset', 'a') |
client.zrank('zset', 'a') |
ZREVRANK | r.zrevrank('zset', 'a') |
client.zrevrank('zset', 'a') |
Transactions | ||
MULTI/EXEC | r.pipeline(transaction=True).set('k', 'v').get('k').execute() |
client.exec(Transaction().set('k', 'v').get('k')) |
Lua Scripts | ||
EVAL | r.eval(script, 1, 'key', 'arg') |
client.invoke_script(Script(script), keys=['key'], args=['arg']) |
EVALSHA | r.evalsha(sha, 1, 'key', 'arg') |
client.invoke_script(Script(script), keys=['key'], args=['arg']) |
Custom Commands | ||
Raw Command | r.execute_command('SET', 'key', 'value') |
client.custom_command(['SET', 'key', 'value']) |
Connection Management | ||
Close | r.close() |
client.close() |