最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Django中使用django-redis庫與Redis交互API指南

 更新時間:2025年12月15日 09:17:51   作者:Python游俠  
這篇文章主要介紹了Django緩存與原生Redis的區(qū)別,以及如何在Django中使用Redis的各種數(shù)據(jù)類型進行緩存,文章還提供了一些實戰(zhàn)場景和性能優(yōu)化技巧,幫助開發(fā)者充分利用Redis的強大功能來構(gòu)建高性能的應(yīng)用,需要的朋友可以參考下

一、理解Django緩存與原生Redis的區(qū)別

Django緩存APIRedis原生數(shù)據(jù)類型用途
鍵值對存儲字符串(String)簡單緩存
不支持列表(List)消息隊列、最新列表
不支持集合(Set)去重、共同好友
不支持有序集合(Sorted Set)排行榜、優(yōu)先級隊列
不支持哈希(Hash)對象存儲、多個字段

二、獲取原生Redis連接

要在Django中使用Redis的所有數(shù)據(jù)類型,需要獲取原生Redis連接:

# 方法1:通過django-redis獲取連接
from django_redis import get_redis_connection

# 獲取默認緩存對應(yīng)的Redis連接
redis_conn = get_redis_connection("default")

# 獲取特定緩存的連接
session_conn = get_redis_connection("session")

# 方法2:直接創(chuàng)建連接(不推薦,缺少連接池管理)
import redis
redis_client = redis.Redis(
    host='localhost',
    port=6379,
    db=0,
    password=None
)

三、字符串類型(String)操作

雖然Django緩存API支持字符串,但Redis有更多功能:

1. 帶過期時間的操作

def string_operations():
    """Redis字符串操作"""
    redis_conn = get_redis_connection("default")
    
    # 1. 設(shè)置帶過期時間的鍵
    redis_conn.setex("session:user:123", 3600, "session_data")  # 1小時后過期
    
    # 2. 設(shè)置多個鍵
    redis_conn.mset({"key1": "value1", "key2": "value2"})
    
    # 3. 獲取字符串的一部分
    redis_conn.set("message", "Hello World")
    part = redis_conn.getrange("message", 0, 4)  # "Hello"
    
    # 4. 追加字符串
    redis_conn.append("message", " Redis!")
    
    # 5. 獲取字符串長度
    length = redis_conn.strlen("message")
    
    # 6. 設(shè)置鍵的值并返回舊值
    old_value = redis_conn.getset("counter", "100")
    
    # 7. 位操作
    redis_conn.setbit("user:online:2023-10-01", 123, 1)  # 用戶123在線
    redis_conn.getbit("user:online:2023-10-01", 123)  # 檢查是否在線
    
    return {
        "part": part,
        "length": length,
        "old_value": old_value
    }

四、列表類型(List)操作

1. 基本列表操作

def list_operations():
    """Redis列表操作"""
    redis_conn = get_redis_connection("default")
    
    # 1. 左側(cè)推入元素
    redis_conn.lpush("recent_users", "user_123", "user_456", "user_789")
    
    # 2. 右側(cè)推入元素
    redis_conn.rpush("task_queue", "task1", "task2", "task3")
    
    # 3. 左側(cè)彈出元素
    first_user = redis_conn.lpop("recent_users")
    
    # 4. 右側(cè)彈出元素
    last_task = redis_conn.rpop("task_queue")
    
    # 5. 獲取列表長度
    length = redis_conn.llen("recent_users")
    
    # 6. 獲取指定范圍的元素
    users = redis_conn.lrange("recent_users", 0, 9)  # 前10個元素
    
    # 7. 移除元素
    redis_conn.lrem("recent_users", 1, "user_123")  # 刪除1個user_123
    
    # 8. 通過索引獲取元素
    user = redis_conn.lindex("recent_users", 0)  # 獲取第一個
    
    # 9. 設(shè)置指定索引的值
    redis_conn.lset("recent_users", 0, "new_user")
    
    return {
        "first_user": first_user,
        "last_task": last_task,
        "length": length,
        "users": users
    }

2. 實戰(zhàn):消息隊列

class MessageQueue:
    """基于Redis列表的消息隊列"""
    
    def __init__(self, queue_name="default_queue"):
        self.redis_conn = get_redis_connection("default")
        self.queue_name = queue_name
    
    def enqueue(self, message):
        """入隊"""
        import json
        message_str = json.dumps(message)
        return self.redis_conn.rpush(self.queue_name, message_str)
    
    def dequeue(self, timeout=0):
        """出隊(阻塞)"""
        import json
        result = self.redis_conn.blpop(self.queue_name, timeout=timeout)
        if result:
            queue_name, message_str = result
            return json.loads(message_str)
        return None
    
    def size(self):
        """隊列大小"""
        return self.redis_conn.llen(self.queue_name)
    
    def peek(self):
        """查看但不移除"""
        import json
        message_str = self.redis_conn.lindex(self.queue_name, 0)
        if message_str:
            return json.loads(message_str)
        return None

# 使用示例
def process_messages():
    """處理消息隊列"""
    queue = MessageQueue("email_queue")
    
    # 生產(chǎn)者
    queue.enqueue({
        "to": "user@example.com",
        "subject": "Welcome",
        "body": "Hello!"
    })
    
    # 消費者
    while True:
        message = queue.dequeue(timeout=5)  # 阻塞5秒
        if message:
            # 處理消息
            send_email(**message)
        else:
            # 沒有消息,休息一下
            import time
            time.sleep(1)

五、集合類型(Set)操作

1. 基本集合操作

def set_operations():
    """Redis集合操作"""
    redis_conn = get_redis_connection("default")
    
    # 1. 添加元素
    redis_conn.sadd("user_tags:123", "python", "django", "redis")
    redis_conn.sadd("user_tags:456", "python", "javascript", "vue")
    
    # 2. 獲取所有元素
    tags_123 = redis_conn.smembers("user_tags:123")
    
    # 3. 判斷元素是否存在
    is_member = redis_conn.sismember("user_tags:123", "python")
    
    # 4. 移除元素
    redis_conn.srem("user_tags:123", "redis")
    
    # 5. 獲取集合大小
    size = redis_conn.scard("user_tags:123")
    
    # 6. 隨機獲取元素
    random_tag = redis_conn.srandmember("user_tags:123", 1)
    
    # 7. 集合運算
    # 交集:都喜歡的標簽
    common_tags = redis_conn.sinter("user_tags:123", "user_tags:456")
    
    # 并集:所有標簽
    all_tags = redis_conn.sunion("user_tags:123", "user_tags:456")
    
    # 差集:用戶123有但456沒有的標簽
    diff_tags = redis_conn.sdiff("user_tags:123", "user_tags:456")
    
    return {
        "tags_123": tags_123,
        "is_member": is_member,
        "size": size,
        "common_tags": common_tags
    }

2. 實戰(zhàn):用戶標簽系統(tǒng)

class UserTagSystem:
    """基于Redis集合的用戶標簽系統(tǒng)"""
    
    def __init__(self):
        self.redis_conn = get_redis_connection("default")
    
    def add_tag(self, user_id, tag):
        """為用戶添加標簽"""
        return self.redis_conn.sadd(f"user_tags:{user_id}", tag)
    
    def remove_tag(self, user_id, tag):
        """移除用戶標簽"""
        return self.redis_conn.srem(f"user_tags:{user_id}", tag)
    
    def get_user_tags(self, user_id):
        """獲取用戶所有標簽"""
        return self.redis_conn.smembers(f"user_tags:{user_id}")
    
    def has_tag(self, user_id, tag):
        """檢查用戶是否有某個標簽"""
        return self.redis_conn.sismember(f"user_tags:{user_id}", tag)
    
    def find_users_with_tag(self, tag):
        """查找具有某個標簽的所有用戶"""
        # 需要遍歷所有用戶,實際應(yīng)用中可以使用反向索引
        pattern = "user_tags:*"
        matching_users = []
        
        # 使用SCAN避免阻塞
        cursor = 0
        while True:
            cursor, keys = self.redis_conn.scan(cursor, pattern, count=100)
            for key in keys:
                if self.redis_conn.sismember(key, tag):
                    user_id = key.decode().split(":")[1]
                    matching_users.append(user_id)
            
            if cursor == 0:
                break
        
        return matching_users
    
    def get_common_tags(self, user_ids):
        """獲取多個用戶的共同標簽"""
        if len(user_ids) < 2:
            return []
        
        keys = [f"user_tags:{user_id}" for user_id in user_ids]
        return self.redis_conn.sinter(*keys)
    
    def get_recommended_tags(self, user_id):
        """根據(jù)相似用戶推薦標簽"""
        user_tags = self.get_user_tags(user_id)
        if not user_tags:
            return []
        
        # 查找有相同標簽的用戶
        similar_users = []
        for tag in user_tags:
            users_with_tag = self.find_users_with_tag(tag)
            similar_users.extend(users_with_tag)
        
        # 去重并排除自己
        similar_users = set(similar_users) - {user_id}
        
        # 收集相似用戶的標簽
        all_tags = set()
        for similar_user in list(similar_users)[:10]:  # 只看前10個相似用戶
            tags = self.get_user_tags(similar_user)
            all_tags.update(tags)
        
        # 排除用戶已有的標簽
        recommended = all_tags - set(user_tags)
        
        return list(recommended)[:10]  # 返回前10個推薦標簽

六、有序集合類型(Sorted Set)操作

1. 基本有序集合操作

def sorted_set_operations():
    """Redis有序集合操作"""
    redis_conn = get_redis_connection("default")
    
    # 1. 添加元素(帶分數(shù))
    redis_conn.zadd("leaderboard", {
        "player1": 1000,
        "player2": 1500,
        "player3": 800,
        "player4": 2000
    })
    
    # 2. 增加分數(shù)
    redis_conn.zincrby("leaderboard", 100, "player1")  # player1增加100分
    
    # 3. 按分數(shù)升序獲取
    ascending = redis_conn.zrange("leaderboard", 0, -1, withscores=True)
    
    # 4. 按分數(shù)降序獲取
    descending = redis_conn.zrevrange("leaderboard", 0, -1, withscores=True)
    
    # 5. 獲取排名
    rank = redis_conn.zrevrank("leaderboard", "player1")  # 降序排名,0為第一
    
    # 6. 獲取分數(shù)
    score = redis_conn.zscore("leaderboard", "player1")
    
    # 7. 獲取分數(shù)范圍內(nèi)的元素
    top_players = redis_conn.zrangebyscore("leaderboard", 1000, 3000, withscores=True)
    
    # 8. 移除元素
    redis_conn.zrem("leaderboard", "player4")
    
    # 9. 獲取集合大小
    size = redis_conn.zcard("leaderboard")
    
    # 10. 統(tǒng)計分數(shù)區(qū)間的元素數(shù)量
    count = redis_conn.zcount("leaderboard", 1000, 3000)
    
    return {
        "rank": rank,
        "score": score,
        "top_3": descending[:3],
        "count": count
    }

2. 實戰(zhàn):排行榜系統(tǒng)

class Leaderboard:
    """基于Redis有序集合的排行榜系統(tǒng)"""
    
    def __init__(self, leaderboard_name="default_leaderboard"):
        self.redis_conn = get_redis_connection("default")
        self.name = leaderboard_name
    
    def add_score(self, player_id, score):
        """添加或更新分數(shù)"""
        return self.redis_conn.zincrby(self.name, score, player_id)
    
    def get_top_n(self, n=10):
        """獲取前N名"""
        return self.redis_conn.zrevrange(
            self.name, 0, n-1, withscores=True
        )
    
    def get_player_rank(self, player_id):
        """獲取玩家排名(從1開始)"""
        rank = self.redis_conn.zrevrank(self.name, player_id)
        if rank is not None:
            return rank + 1
        return None
    
    def get_player_score(self, player_id):
        """獲取玩家分數(shù)"""
        return self.redis_conn.zscore(self.name, player_id)
    
    def get_players_around(self, player_id, range_size=5):
        """獲取玩家附近的排名"""
        rank = self.get_player_rank(player_id)
        if rank is None:
            return []
        
        start = max(0, rank - 1 - range_size)
        end = rank - 1 + range_size
        
        players = self.redis_conn.zrevrange(
            self.name, start, end, withscores=True
        )
        
        return [
            {"player": player, "score": score, "rank": idx + start + 1}
            for idx, (player, score) in enumerate(players)
        ]
    
    def get_season_leaderboard(self, season_id, top_n=100):
        """獲取賽季排行榜"""
        season_key = f"{self.name}:season:{season_id}"
        
        # 檢查是否有緩存的賽季排行榜
        cached = self.redis_conn.get(season_key)
        if cached:
            import json
            return json.loads(cached)
        
        # 計算賽季排行榜
        season_end = int(season_id)  # 假設(shè)season_id是時間戳
        season_start = season_end - 86400 * 30  # 30天
        
        # 獲取賽季期間有分數(shù)的玩家
        all_players = self.redis_conn.zrevrangebyscore(
            f"{self.name}:daily:{season_end}",
            season_start, season_end,
            withscores=False
        )
        
        # 計算每個玩家的賽季總分
        pipe = self.redis_conn.pipeline()
        for player in all_players:
            pipe.zscore(f"{self.name}:daily", player)
        
        scores = pipe.execute()
        
        # 創(chuàng)建有序集合
        season_data = {player: score for player, score in zip(all_players, scores) if score}
        
        if season_data:
            season_leaderboard_key = f"{self.name}:season_temp:{season_id}"
            self.redis_conn.zadd(season_leaderboard_key, season_data)
            
            # 獲取前N名
            top_players = self.redis_conn.zrevrange(
                season_leaderboard_key, 0, top_n-1, withscores=True
            )
            
            # 刪除臨時鍵
            self.redis_conn.delete(season_leaderboard_key)
            
            # 緩存結(jié)果
            import json
            self.redis_conn.setex(
                season_key,
                3600,  # 緩存1小時
                json.dumps(top_players)
            )
            
            return top_players
        
        return []


# 游戲積分系統(tǒng)示例
class GameScoreSystem:
    """游戲積分系統(tǒng)"""
    
    def __init__(self, game_id):
        self.redis_conn = get_redis_connection("default")
        self.game_id = game_id
        self.leaderboard = Leaderboard(f"game:{game_id}:leaderboard")
    
    def record_score(self, user_id, score, level, time_spent):
        """記錄游戲得分"""
        import time
        timestamp = int(time.time())
        
        # 1. 更新總排行榜
        self.leaderboard.add_score(user_id, score)
        
        # 2. 記錄詳細得分(使用哈希)
        score_key = f"game:{self.game_id}:score:{user_id}:{timestamp}"
        self.redis_conn.hmset(score_key, {
            "score": score,
            "level": level,
            "time_spent": time_spent,
            "timestamp": timestamp
        })
        
        # 設(shè)置24小時過期
        self.redis_conn.expire(score_key, 86400)
        
        # 3. 更新每日排行榜
        date_str = time.strftime("%Y%m%d")
        daily_key = f"game:{self.game_id}:daily:{date_str}"
        self.redis_conn.zincrby(daily_key, score, user_id)
        
        # 4. 更新關(guān)卡排行榜
        level_key = f"game:{self.game_id}:level:{level}"
        self.redis_conn.zincrby(level_key, 1, user_id)  # 通關(guān)次數(shù)
        
        return {
            "rank": self.leaderboard.get_player_rank(user_id),
            "score": self.leaderboard.get_player_score(user_id)
        }

七、哈希類型(Hash)操作

1. 基本哈希操作

def hash_operations():
    """Redis哈希操作"""
    redis_conn = get_redis_connection("default")
    
    # 1. 設(shè)置單個字段
    redis_conn.hset("user:123", "name", "張三")
    
    # 2. 設(shè)置多個字段
    redis_conn.hmset("user:123", {
        "age": 25,
        "email": "zhangsan@example.com",
        "city": "北京"
    })
    
    # 3. 獲取單個字段
    name = redis_conn.hget("user:123", "name")
    
    # 4. 獲取多個字段
    fields = redis_conn.hmget("user:123", ["name", "age", "email"])
    
    # 5. 獲取所有字段
    all_fields = redis_conn.hgetall("user:123")
    
    # 6. 獲取所有字段名
    field_names = redis_conn.hkeys("user:123")
    
    # 7. 獲取所有字段值
    field_values = redis_conn.hvals("user:123")
    
    # 8. 檢查字段是否存在
    exists = redis_conn.hexists("user:123", "name")
    
    # 9. 刪除字段
    redis_conn.hdel("user:123", "city")
    
    # 10. 獲取字段數(shù)量
    field_count = redis_conn.hlen("user:123")
    
    # 11. 增加數(shù)值字段的值
    redis_conn.hincrby("user:123", "age", 1)  # 增加1歲
    
    return {
        "name": name,
        "fields": fields,
        "exists": exists,
        "field_count": field_count
    }

2. 實戰(zhàn):購物車系統(tǒng)

class ShoppingCart:
    """基于Redis哈希的購物車系統(tǒng)"""
    
    def __init__(self, cart_id=None):
        self.redis_conn = get_redis_connection("default")
        self.cart_id = cart_id or f"cart:{int(time.time())}"
    
    def add_item(self, product_id, quantity=1, price=None):
        """添加商品到購物車"""
        cart_key = f"cart:items:{self.cart_id}"
        
        # 獲取當前數(shù)量
        current_quantity = self.redis_conn.hget(cart_key, product_id)
        if current_quantity:
            quantity = int(current_quantity) + quantity
        
        # 更新購物車
        self.redis_conn.hset(cart_key, product_id, quantity)
        
        # 如果提供了價格,存儲到商品信息
        if price is not None:
            product_key = f"cart:product_info:{self.cart_id}"
            self.redis_conn.hset(product_key, product_id, price)
        
        return quantity
    
    def remove_item(self, product_id, quantity=None):
        """從購物車移除商品"""
        cart_key = f"cart:items:{self.cart_id}"
        
        if quantity is None:
            # 移除整個商品
            self.redis_conn.hdel(cart_key, product_id)
            
            # 同時移除價格信息
            product_key = f"cart:product_info:{self.cart_id}"
            self.redis_conn.hdel(product_key, product_id)
        else:
            # 減少數(shù)量
            current_quantity = self.redis_conn.hget(cart_key, product_id)
            if current_quantity:
                new_quantity = int(current_quantity) - quantity
                if new_quantity > 0:
                    self.redis_conn.hset(cart_key, product_id, new_quantity)
                else:
                    self.remove_item(product_id)
    
    def get_items(self):
        """獲取購物車所有商品"""
        cart_key = f"cart:items:{self.cart_id}"
        items = self.redis_conn.hgetall(cart_key)
        
        product_key = f"cart:product_info:{self.cart_id}"
        prices = self.redis_conn.hgetall(product_key)
        
        result = []
        for product_id, quantity in items.items():
            product_id = product_id.decode() if isinstance(product_id, bytes) else product_id
            quantity = int(quantity)
            
            price = prices.get(product_id.encode() if isinstance(product_id, str) else product_id)
            if price:
                price = float(price.decode() if isinstance(price, bytes) else price)
            
            result.append({
                "product_id": product_id,
                "quantity": quantity,
                "price": price,
                "subtotal": price * quantity if price else None
            })
        
        return result
    
    def get_total(self):
        """計算購物車總價"""
        items = self.get_items()
        return sum(item.get("subtotal", 0) for item in items)
    
    def clear(self):
        """清空購物車"""
        cart_key = f"cart:items:{self.cart_id}"
        product_key = f"cart:product_info:{self.cart_id}"
        
        self.redis_conn.delete(cart_key, product_key)
    
    def get_item_count(self):
        """獲取購物車商品總數(shù)"""
        cart_key = f"cart:items:{self.cart_id}"
        items = self.redis_conn.hvals(cart_key)
        return sum(int(q) for q in items) if items else 0
    
    def checkout(self):
        """結(jié)賬"""
        items = self.get_items()
        
        if not items:
            return {"success": False, "message": "購物車為空"}
        
        # 生成訂單
        import uuid
        order_id = str(uuid.uuid4())
        
        # 保存訂單
        order_key = f"order:{order_id}"
        self.redis_conn.hmset(order_key, {
            "cart_id": self.cart_id,
            "total": self.get_total(),
            "created_at": int(time.time()),
            "status": "pending"
        })
        
        # 保存訂單商品
        for item in items:
            self.redis_conn.hset(
                f"{order_key}:items",
                item["product_id"],
                item["quantity"]
            )
        
        # 清空購物車
        self.clear()
        
        return {
            "success": True,
            "order_id": order_id,
            "total": self.get_total(),
            "item_count": len(items)
        }

八、高級數(shù)據(jù)結(jié)構(gòu)組合應(yīng)用

1. 社交關(guān)系系統(tǒng)

class SocialNetwork:
    """基于Redis的社交關(guān)系系統(tǒng)"""
    
    def __init__(self):
        self.redis_conn = get_redis_connection("default")
    
    def follow(self, follower_id, followee_id):
        """關(guān)注用戶"""
        # 添加到關(guān)注列表(集合)
        self.redis_conn.sadd(f"user:{follower_id}:following", followee_id)
        self.redis_conn.sadd(f"user:{followee_id}:followers", follower_id)
        
        # 記錄時間線(有序集合)
        import time
        timestamp = time.time()
        
        # 獲取關(guān)注用戶的動態(tài)
        posts_key = f"user:{followee_id}:posts"
        posts = self.redis_conn.zrevrangebyscore(
            posts_key, timestamp - 86400 * 7, timestamp,  # 最近7天的帖子
            withscores=True
        )
        
        # 添加到關(guān)注者的時間線
        timeline_key = f"user:{follower_id}:timeline"
        for post_id, post_time in posts:
            self.redis_conn.zadd(timeline_key, {post_id: post_time})
        
        # 限制時間線長度
        self.redis_conn.zremrangebyrank(timeline_key, 0, -1000)  # 只保留最新的1000條
    
    def unfollow(self, follower_id, followee_id):
        """取消關(guān)注"""
        self.redis_conn.srem(f"user:{follower_id}:following", followee_id)
        self.redis_conn.srem(f"user:{followee_id}:followers", follower_id)
    
    def get_followers(self, user_id, page=1, per_page=20):
        """獲取粉絲列表"""
        key = f"user:{user_id}:followers"
        start = (page - 1) * per_page
        end = start + per_page - 1
        
        # 使用集合獲取粉絲
        followers = self.redis_conn.smembers(key)
        
        # 獲取粉絲詳細信息
        followers_list = []
        for follower_id in list(followers)[start:end+1]:
            user_info = self.redis_conn.hgetall(f"user:{follower_id}")
            followers_list.append(user_info)
        
        return {
            "followers": followers_list,
            "total": self.redis_conn.scard(key),
            "page": page,
            "per_page": per_page
        }
    
    def get_mutual_followers(self, user1_id, user2_id):
        """獲取共同關(guān)注的人"""
        key1 = f"user:{user1_id}:following"
        key2 = f"user:{user2_id}:following"
        
        return self.redis_conn.sinter(key1, key2)
    
    def post_update(self, user_id, content):
        """發(fā)布動態(tài)"""
        import time
        import uuid
        
        post_id = str(uuid.uuid4())
        timestamp = time.time()
        
        # 存儲帖子內(nèi)容(哈希)
        post_key = f"post:{post_id}"
        self.redis_conn.hmset(post_key, {
            "id": post_id,
            "user_id": user_id,
            "content": content,
            "timestamp": timestamp,
            "likes": 0,
            "comments": 0
        })
        
        # 添加到用戶的帖子列表(有序集合)
        user_posts_key = f"user:{user_id}:posts"
        self.redis_conn.zadd(user_posts_key, {post_id: timestamp})
        
        # 添加到粉絲的時間線
        followers_key = f"user:{user_id}:followers"
        followers = self.redis_conn.smembers(followers_key)
        
        for follower_id in followers:
            timeline_key = f"user:{follower_id}:timeline"
            self.redis_conn.zadd(timeline_key, {post_id: timestamp})
            self.redis_conn.zremrangebyrank(timeline_key, 0, -1000)
        
        return post_id
    
    def get_timeline(self, user_id, page=1, per_page=20):
        """獲取時間線"""
        timeline_key = f"user:{user_id}:timeline"
        start = (page - 1) * per_page
        end = start + per_page - 1
        
        # 獲取帖子ID
        post_ids = self.redis_conn.zrevrange(timeline_key, start, end)
        
        # 獲取帖子詳情
        posts = []
        for post_id in post_ids:
            post = self.redis_conn.hgetall(f"post:{post_id}")
            if post:
                posts.append(post)
        
        return {
            "posts": posts,
            "total": self.redis_conn.zcard(timeline_key),
            "page": page,
            "per_page": per_page
        }

2. 實時統(tǒng)計系統(tǒng)

class RealTimeStatistics:
    """實時統(tǒng)計系統(tǒng)"""
    
    def __init__(self):
        self.redis_conn = get_redis_connection("default")
    
    def record_event(self, event_type, user_id=None, data=None):
        """記錄事件"""
        import time
        timestamp = int(time.time())
        
        # 1. 記錄到全局事件流(列表)
        event_id = f"{timestamp}:{user_id}:{event_type}"
        self.redis_conn.lpush("events:stream", event_id)
        
        # 2. 按類型計數(shù)(哈希)
        today = time.strftime("%Y%m%d")
        daily_key = f"stats:events:{today}"
        self.redis_conn.hincrby(daily_key, event_type, 1)
        
        # 3. 記錄用戶事件(有序集合)
        if user_id:
            user_events_key = f"user:{user_id}:events"
            self.redis_conn.zadd(user_events_key, {event_type: timestamp})
            
            # 用戶最后活躍時間
            self.redis_conn.hset(f"user:{user_id}:activity", "last_active", timestamp)
        
        # 4. 按小時統(tǒng)計(哈希)
        hour = time.strftime("%Y%m%d%H")
        hour_key = f"stats:hourly:{hour}"
        self.redis_conn.hincrby(hour_key, event_type, 1)
        
        return event_id
    
    def get_daily_stats(self, date_str=None):
        """獲取每日統(tǒng)計"""
        import time
        if not date_str:
            date_str = time.strftime("%Y%m%d")
        
        key = f"stats:events:{date_str}"
        return self.redis_conn.hgetall(key)
    
    def get_hourly_trend(self, event_type, hours=24):
        """獲取小時趨勢"""
        import time
        from datetime import datetime, timedelta
        
        now = datetime.now()
        trend = []
        
        for i in range(hours):
            hour = now - timedelta(hours=i)
            hour_str = hour.strftime("%Y%m%d%H")
            key = f"stats:hourly:{hour_str}"
            
            count = self.redis_conn.hget(key, event_type)
            trend.append({
                "hour": hour_str,
                "count": int(count) if count else 0
            })
        
        return list(reversed(trend))  # 從早到晚
    
    def get_active_users(self, minutes=5):
        """獲取活躍用戶(最近N分鐘有活動的用戶)"""
        import time
        
        # 使用集合存儲活躍用戶
        active_users_key = "users:active"
        
        # 獲取所有用戶
        pattern = "user:*:activity"
        active_users = set()
        
        cursor = 0
        while True:
            cursor, keys = self.redis_conn.scan(cursor, pattern, count=100)
            
            for key in keys:
                # 解析用戶ID
                user_id = key.decode().split(":")[1]
                
                # 檢查最后活躍時間
                last_active = self.redis_conn.hget(key, "last_active")
                if last_active:
                    last_active = int(last_active)
                    if time.time() - last_active < minutes * 60:
                        active_users.add(user_id)
            
            if cursor == 0:
                break
        
        return list(active_users)

九、性能優(yōu)化技巧

1. 使用管道(Pipeline)

def use_pipeline():
    """使用管道批量操作"""
    redis_conn = get_redis_connection("default")
    
    # 創(chuàng)建管道
    pipe = redis_conn.pipeline()
    
    # 批量添加命令
    for i in range(100):
        pipe.set(f"key:{i}", f"value:{i}")
        pipe.expire(f"key:{i}", 3600)
    
    # 一次執(zhí)行所有命令
    results = pipe.execute()
    
    return len(results)  # 200個結(jié)果

2. 使用Lua腳本

def use_lua_script():
    """使用Lua腳本實現(xiàn)原子操作"""
    redis_conn = get_redis_connection("default")
    
    # 原子增加分數(shù)并更新排行榜
    lua_script = """
    local player = KEYS[1]
    local score = tonumber(ARGV[1])
    local leaderboard = KEYS[2]
    
    -- 增加分數(shù)
    local new_score = redis.call('ZINCRBY', leaderboard, score, player)
    
    -- 獲取排名
    local rank = redis.call('ZREVRANK', leaderboard, player)
    
    -- 返回結(jié)果
    return {new_score, rank}
    """
    
    # 執(zhí)行腳本
    result = redis_conn.eval(
        lua_script,
        2,  # 2個KEYS
        "player_123",  # KEYS[1]
        "leaderboard",  # KEYS[2]
        100  # ARGV[1]
    )
    
    return {
        "new_score": float(result[0]),
        "rank": int(result[1]) + 1 if result[1] is not None else None
    }

十、總結(jié)

通過原生Redis連接,你可以在Django中使用Redis的所有數(shù)據(jù)類型:

數(shù)據(jù)類型主要用途Django對應(yīng)
字符串簡單緩存、計數(shù)器Django緩存API
列表消息隊列、時間線無,需手動實現(xiàn)
集合標簽、好友關(guān)系無,需手動實現(xiàn)
有序集合排行榜、優(yōu)先級隊列無,需手動實現(xiàn)
哈希對象存儲、購物車無,需手動實現(xiàn)

最佳實踐:

  1. 簡單緩存使用Django緩存API
  2. 復(fù)雜數(shù)據(jù)結(jié)構(gòu)使用原生Redis連接
  3. 批量操作使用管道
  4. 原子操作使用Lua腳本
  5. 合理設(shè)置過期時間,避免內(nèi)存泄漏

這樣,你就可以充分利用Redis的所有功能來構(gòu)建高性能的Django應(yīng)用了。

以上就是Django中使用django-redis庫與Redis交互API指南的詳細內(nèi)容,更多關(guān)于Django django-redis與Redis交互API的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • CNN的Pytorch實現(xiàn)(LeNet)

    CNN的Pytorch實現(xiàn)(LeNet)

    本文主要從CNN的Pytorch實現(xiàn)庫導(dǎo)入,模型定義,數(shù)據(jù)加載、處理,模型訓(xùn)練,代碼匯總等方面入手介紹,運用代碼講解相關(guān)內(nèi)容非常的詳細,大家如果有需要了解相關(guān)知識的可以參考這篇文章
    2021-09-09
  • Django+Ajax異步刷新/定時自動刷新實例詳解

    Django+Ajax異步刷新/定時自動刷新實例詳解

    AJAX是前端技術(shù)的集合,包括JavaScript、XML、HTML、CSS等,下面這篇文章主要給大家介紹了關(guān)于Django+Ajax異步刷新/定時自動刷新的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-10-10
  • 從基礎(chǔ)到高級詳解Python中文件操作的全攻略實戰(zhàn)指南

    從基礎(chǔ)到高級詳解Python中文件操作的全攻略實戰(zhàn)指南

    在Python編程中,文件操作是連接程序與外部存儲的橋梁,本文將從基礎(chǔ)讀寫講起,逐步深入到高效處理、異常管理、二進制操作等高級場景,希望對大家有所幫助
    2025-10-10
  • django執(zhí)行原始查詢sql,并返回Dict字典例子

    django執(zhí)行原始查詢sql,并返回Dict字典例子

    這篇文章主要介紹了django執(zhí)行原始查詢sql,并返回Dict字典例子,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-04-04
  • PyPDF2讀取PDF文件內(nèi)容保存到本地TXT實例

    PyPDF2讀取PDF文件內(nèi)容保存到本地TXT實例

    這篇文章主要介紹了PyPDF2讀取PDF文件內(nèi)容保存到本地TXT實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-05-05
  • Python實現(xiàn)冒泡排序算法的示例解析

    Python實現(xiàn)冒泡排序算法的示例解析

    冒泡排序(Bubble Sort)是一種簡單的排序算法。本文將詳細為大家講講Python實現(xiàn)冒泡排序算法的方法,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-06-06
  • python中matplotlib條件背景顏色的實現(xiàn)

    python中matplotlib條件背景顏色的實現(xiàn)

    這篇文章主要給大家介紹了關(guān)于python中matplotlib條件背景顏色的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用python具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 解決Pycharm后臺indexing導(dǎo)致不能run的問題

    解決Pycharm后臺indexing導(dǎo)致不能run的問題

    今天小編就為大家分享一篇解決Pycharm后臺indexing導(dǎo)致不能run的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-06-06
  • Python 交互式可視化的利器Bokeh的使用

    Python 交互式可視化的利器Bokeh的使用

    Bokeh是一個專注于Web端交互式數(shù)據(jù)可視化的Python庫,本文主要介紹了Python 交互式可視化的利器Bokeh的使用,具有一定的參考價值,感興趣的可以了解一下
    2025-04-04
  • 一文詳解如何在Matplotlib中更改圖例字體大小

    一文詳解如何在Matplotlib中更改圖例字體大小

    在我們處理數(shù)據(jù)的時候,需要對大量的數(shù)據(jù)進行繪圖,就免不了要使用到Matplotlib,下面這篇文章主要給大家介紹了關(guān)于如何在Matplotlib中更改圖例字體大小的相關(guān)資料,需要的朋友可以參考下
    2023-05-05

最新評論

鱼台县| 土默特左旗| 体育| 荥阳市| 景洪市| 丹江口市| 仁化县| 盱眙县| 阿克陶县| 宣汉县| 广平县| 延安市| 霍州市| 嵊泗县| 博兴县| 自贡市| 新平| 顺昌县| 沅陵县| 丰县| 章丘市| 偏关县| 林芝县| 樟树市| 星子县| 太和县| 买车| 永寿县| 许昌县| 湘乡市| 邹平县| 石林| 昌平区| 华容县| 新干县| 宁阳县| 吉木乃县| 胶州市| 广汉市| 常熟市| 凤阳县|