Python自动化操作Redis的15个实用脚本

Python自动化操作Redis的15个实用脚本

Redis作为高性能的键值数据库,在现代应用开发中扮演着重要角色。Python通过redis-py库提供了丰富的Redis操作接口,能够帮助开发者高效地实现数据缓存、会话管理、消息队列等多种功能。本文将介绍15个实用的自动化脚本,涵盖数据操作、性能优化和高级功能等多个典型场景。

环境准备

首先确保已安装redis-py库:

pip install redis

所有示例默认连接本地Redis服务器(localhost:6379,数据库0),实际使用时请根据生产环境调整连接参数。

1. 基础键值操作

场景:简单的数据存储与检索

import redis

def basic_key_operations():
    r = redis.Redis(host='localhost', port=6379, db=0)
    
    # 设置带过期时间的键值
    r.setex('session:user123', 3600, 'active')
    
    # 获取值
    status = r.get('session:user123')
    print(f"Session status: {status.decode() if status else 'Not found'}")
    
    # 检查键是否存在
    exists = r.exists('session:user123')
    print(f"Key exists: {exists}")

if __name__ == "__main__":
    basic_key_operations()

2. 批量操作键值

场景:高效处理大量数据

def batch_operations():
    r = redis.Redis(host='localhost', port=6379, db=0)
    
    # 批量设置多个键值
    data = {
        'user:1:name': 'Alice',
        'user:1:email': 'alice@example.com',
        'user:1:age': '25'
    }
    r.mset(data)
    
    # 批量获取多个键值
    keys = ['user:1:name', 'user:1:email', 'user:1:age']
    values = r.mget(keys)
    for key, value in zip(keys, values):
        print(f"{key}: {value.decode() if value else 'None'}")

3. 哈希表高级操作

场景:存储结构化对象

def advanced_hash_operations():
    r = redis.Redis(host='localhost', port=6379, db=0)
    
    user_id = "user:1001"
    
    # 设置多个字段
    user_data = {
        'name': 'Bob Smith',
        'email': 'bob@example.com',
        'score': '95',
        'last_login': '2025-12-25'
    }
    r.hset(user_id, mapping=user_data)
    
    # 获取所有字段
    all_fields = r.hgetall(user_id)
    print("User data:")
    for field, value in all_fields.items():
        print(f"  {field.decode()}: {value.decode()}")
    
    # 增加数值字段
    r.hincrby(user_id, 'score', 5)
    new_score = r.hget(user_id, 'score')
    print(f"Updated score: {new_score.decode()}")

4. 列表队列操作

场景:实现任务队列

def queue_operations():
    r = redis.Redis(host='localhost', port=6379, db=0)
    queue_key = 'task_queue'
    
    # 生产者:添加任务到队列
    tasks = ['process_data', 'send_email', 'generate_report', 'cleanup']
    for task in tasks:
        r.lpush(queue_key, task)
        print(f"Added task: {task}")
    
    # 消费者:处理任务
    while True:
        task = r.brpop(queue_key, timeout=1)
        if task:
            task_name = task[1].decode()
            print(f"Processing task: {task_name}")
            # 模拟任务处理
            import time
            time.sleep(0.5)
            print(f"Completed: {task_name}")
        else:
            print("No more tasks in queue")
            break

5. 集合运算

场景:用户标签系统

def set_operations():
    r = redis.Redis(host='localhost', port=6379, db=0)
    
    # 用户标签集合
    r.sadd('user:101:tags', 'python', 'redis', 'backend')
    r.sadd('user:102:tags', 'python', 'frontend', 'javascript')
    r.sadd('user:103:tags', 'redis', 'database', 'backend')
    
    # 查找共同标签
    common_tags = r.sinter('user:101:tags', 'user:103:tags')
    print("Common tags between user 101 and 103:")
    for tag in common_tags:
        print(f"  - {tag.decode()}")
    
    # 合并所有标签
    all_tags = r.sunion('user:101:tags', 'user:102:tags', 'user:103:tags')
    print("\nAll unique tags:")
    for tag in sorted(all_tags):
        print(f"  - {tag.decode()}")

6. 有序集合排行榜

场景:游戏得分排行榜

def leaderboard_system():
    r = redis.Redis(host='localhost', port=6379, db=0)
    leaderboard_key = 'game:leaderboard'
    
    # 添加玩家得分
    players = {
        'player1': 1500,
        'player2': 2200,
        'player3': 1800,
        'player4': 2500,
        'player5': 1900
    }
    r.zadd(leaderboard_key, players)
    
    # 获取前3名
    top_players = r.zrevrange(leaderboard_key, 0, 2, withscores=True)
    print("Top 3 Players:")
    for rank, (player, score) in enumerate(top_players, 1):
        print(f"{rank}. {player.decode()}: {int(score)} points")
    
    # 获取玩家排名
    player_rank = r.zrevrank(leaderboard_key, 'player3')
    player_score = r.zscore(leaderboard_key, 'player3')
    print(f"\nPlayer3 rank: {player_rank + 1 if player_rank is not None else 'N/A'}")
    print(f"Player3 score: {player_score}")

7. 发布订阅模式

场景:实时通知系统

import threading
import time

def pubsub_system():
    r = redis.Redis(host='localhost', port=6379, db=0)
    
    def subscriber(channel_name):
        pubsub = r.pubsub()
        pubsub.subscribe(channel_name)
        print(f"Subscriber started on channel: {channel_name}")
        
        for message in pubsub.listen():
            if message['type'] == 'message':
                data = message['data'].decode()
                print(f"Received: {data}")
                if data == 'exit':
                    break
    
    # 启动订阅者线程
    channel = 'notifications'
    sub_thread = threading.Thread(target=subscriber, args=(channel,))
    sub_thread.daemon = True
    sub_thread.start()
    
    time.sleep(1)  # 等待订阅者准备
    
    # 发布消息
    messages = [
        "System started",
        "User logged in",
        "Data updated",
        "exit"
    ]
    
    for msg in messages:
        r.publish(channel, msg)
        time.sleep(0.5)
    
    sub_thread.join(timeout=2)

8. 管道批量操作

场景:减少网络延迟

def pipeline_performance():
    r = redis.Redis(host='localhost', port=6379, db=0)
    
    # 不使用管道
    start = time.time()
    for i in range(100):
        r.set(f'temp:{i}', f'value:{i}')
    without_pipeline = time.time() - start
    
    # 清理数据
    for i in range(100):
        r.delete(f'temp:{i}')
    
    # 使用管道
    start = time.time()
    pipe = r.pipeline()
    for i in range(100):
        pipe.set(f'temp:{i}', f'value:{i}')
    pipe.execute()
    with_pipeline = time.time() - start
    
    print(f"Without pipeline: {without_pipeline:.3f} seconds")
    print(f"With pipeline: {with_pipeline:.3f} seconds")
    print(f"Performance improvement: {without_pipeline/with_pipeline:.1f}x")

9. 事务保证原子性

场景:账户余额转账

def transaction_example():
    r = redis.Redis(host='localhost', port=6379, db=0)
    
    # 初始化账户余额
    r.set('account:A', '1000')
    r.set('account:B', '500')
    
    def transfer_funds(from_account, to_account, amount):
        pipe = r.pipeline(transaction=True)
        
        try:
            # 监视账户变化
            pipe.watch(from_account, to_account)
            
            # 检查余额
            from_balance = int(pipe.get(from_account) or 0)
            if from_balance < amount:
                print("Insufficient funds")
                return False
            
            # 开始事务
            pipe.multi()
            pipe.decrby(from_account, amount)
            pipe.incrby(to_account, amount)
            pipe.execute()
            
            print(f"Transferred {amount} from {from_account} to {to_account}")
            return True
            
        except redis.WatchError:
            print("Transaction failed due to concurrent modification")
            return False
        finally:
            pipe.reset()
    
    # 执行转账
    transfer_funds('account:A', 'account:B', 200)
    
    # 验证结果
    print(f"Account A: {r.get('account:A').decode()}")
    print(f"Account B: {r.get('account:B').decode()}")

10. Lua脚本执行

场景:复杂原子操作

def lua_scripting():
    r = redis.Redis(host='localhost', port=6379, db=0)
    
    # Lua脚本:原子性地检查并设置值
    lua_script = """
    local key = KEYS
    local value = ARGV
    local ttl = ARGV
    
    local current = redis.call('GET', key)
    if current then
        return {false, current}
    else
        redis.call('SET', key, value)
        redis.call('EXPIRE', key, ttl)
        return {true, value}
    end
    """
    
    # 注册脚本
    script = r.register_script(lua_script)
    
    # 执行脚本
    key = 'cache:item'
    result = script(keys=[key], args=['cached_data', '60'])
    
    if result[0]:
        print(f"Cache set successfully: {result[1]}")
    else:
        print(f"Cache already exists: {result[1]}")

11. 键过期与TTL管理

场景:缓存失效管理

def expiration_management():
    r = redis.Redis(host='localhost', port=6379, db=0)
    
    # 设置带过期时间的键
    cache_key = 'api:response:user:123'
    r.setex(cache_key, 300, '{"name": "John", "status": "active"}')  # 5分钟过期
    
    # 检查剩余时间
    ttl = r.ttl(cache_key)
    print(f"Cache will expire in {ttl} seconds")
    
    # 更新过期时间
    if ttl < 60:  # 如果剩余时间小于1分钟
        r.expire(cache_key, 600)  # 延长到10分钟
        print("Cache expiration extended to 10 minutes")
    
    # 设置永久键
    r.set('config:site_name', 'MyApp')
    r.persist('config:site_name')  # 移除过期时间

12. 扫描大键集合

场景:安全遍历大量键

def scan_keys():
    r = redis.Redis(host='localhost', port=6379, db=0)
    
    # 使用SCAN代替KEYS(避免阻塞)
    pattern = 'user:*'
    cursor = '0'
    user_keys = []
    
    while cursor != 0:
        cursor, keys = r.scan(cursor=cursor, match=pattern, count=100)
        user_keys.extend(keys)
    
    print(f"Found {len(user_keys)} user keys")
    
    # 批量获取用户信息
    for i in range(0, len(user_keys), 10):
        batch = user_keys[i:i+10]
        values = r.mget(batch)
        for key, value in zip(batch, values):
            if value:
                print(f"{key.decode()}: {value.decode()[:50]}...")

13. 位图操作

场景:用户在线状态追踪

def bitmap_operations():
    r = redis.Redis(host='localhost', port=6379, db=0)
    
    # 记录用户每日登录状态
    bitmap_key = 'online:2025-12-25'
    
    # 用户ID 1001-1010在25日登录
    for user_id in range(1001, 1011):
        r.setbit(bitmap_key, user_id, 1)
    
    # 检查特定用户是否登录
    user_1005_status = r.getbit(bitmap_key, 1005)
    print(f"User 1005 online: {'Yes' if user_1005_status else 'No'}")
    
    # 统计在线用户数
    online_count = r.bitcount(bitmap_key)
    print(f"Total online users: {online_count}")
    
    # 查找第一个在线的用户
    first_online = r.bitpos(bitmap_key, 1)
    print(f"First online user ID: {first_online}")

14. 地理空间索引

场景:附近位置搜索

def geospatial_operations():
    r = redis.Redis(host='localhost', port=6379, db=0)
    
    # 添加地理位置
    locations_key = 'cities:locations'
    cities = {
        'Beijing': (116.4074, 39.9042),
        'Shanghai': (121.4737, 31.2304),
        'Guangzhou': (113.2644, 23.1291),
        'Shenzhen': (114.0579, 22.5431)
    }
    
    r.geoadd(locations_key, cities)
    
    # 查找附近的城市
    center = (116.4074, 39.9042)  # 北京坐标
    nearby = r.georadius(
        locations_key,
        center[0],
        center[1],
        500,  # 500公里半径
        unit='km',
        withdist=True,
        sort='ASC'
    )
    
    print("Cities within 500km of Beijing:")
    for city, distance in nearby:
        print(f"  {city.decode()}: {distance:.1f} km")
    
    # 计算两个城市距离
    distance = r.geodist(locations_key, 'Beijing', 'Shanghai', unit='km')
    print(f"\nDistance Beijing-Shanghai: {distance} km")

15. 连接池与连接管理

场景:生产环境连接优化

import redis
from redis.connection import ConnectionPool

def connection_pool_management():
    # 创建连接池
    pool = ConnectionPool(
        host='localhost',
        port=6379,
        db=0,
        max_connections=10,
        socket_timeout=5,
        retry_on_timeout=True
    )
    
    # 使用连接池
    r = redis.Redis(connection_pool=pool)
    
    try:
        # 测试连接
        r.ping()
        print("Redis connection successful")
        
        # 性能测试
        import time
        start = time.time()
        
        for i in range(1000):
            r.set(f'test:{i}', f'data:{i}')
        
        elapsed = time.time() - start
        print(f"1000 operations completed in {elapsed:.2f} seconds")
        print(f"Operations per second: {1000/elapsed:.0f}")
        
    except redis.ConnectionError as e:
        print(f"Connection failed: {e}")
    finally:
        # 清理连接池
        pool.disconnect()
        print("Connection pool cleaned up")

这些脚本覆盖了Redis主要应用场景,从基础操作到高级功能,可以帮助开发者高效地实现各种数据存储和处理需求。在实际应用中,建议根据具体业务场景选择合适的操作方式,并结合性能监控和优化策略,可以显著提升应用性能和开发效率。

“无他,惟手熟尔”!有需要的用起来!关注「Nicholas与Pypi」获取更多Python实战!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值