Redis 原理、概念与数据类型;增删改查实例;实现缓存并统计点击量

Redis 原理、概念与数据类型;增删改查实例;实现缓存并统计点击量

目录

[一、Redis 原理、概念与数据类型](#一、Redis 原理、概念与数据类型)

[1.1 Redis 概念](#1.1 Redis 概念)

[1.2 Redis 核心原理](#1.2 Redis 核心原理)

(1)内存存储与持久化

(2)单线程模型

(3)IO多路复用

[1.3 Redis 数据类型](#1.3 Redis 数据类型)

[二、Redis 缓存增删改查实例(Python实现)](#二、Redis 缓存增删改查实例(Python实现))

[2.1 环境准备](#2.1 环境准备)

[2.2 业务场景](#2.2 业务场景)

[2.3 代码实现](#2.3 代码实现)

三、使用Redis实现缓存并统计点击量

[3.1 业务场景](#3.1 业务场景)

[3.2 实现方案](#3.2 实现方案)

[3.3 代码实现](#3.3 代码实现)

四、总结


一、Redis 原理、概念与数据类型

1.1 Redis 概念

Redis(Remote Dictionary Server)是一款​​开源的内存键值对数据库​​,也被称为"数据结构服务器"。它支持多种数据结构(如字符串、哈希、列表等),并提供持久化、事务、发布订阅等功能。核心特点是:

  • ​高性能​:内存存储,读写速度可达10万+ QPS;
  • ​持久化​:支持RDB(快照)和AOF(日志)两种持久化方式;
  • ​多数据结构​:内置丰富的数据类型,适用于复杂场景;
  • ​原子性​:单线程模型保证命令执行的原子性;
  • ​分布式​:支持主从复制、哨兵、集群等分布式方案。
1.2 Redis 核心原理
(1)内存存储与持久化
  • ​内存存储​:数据主要存储在内存中,读写效率极高;但内存断电易失,因此需要持久化机制。
  • ​RDB(Redis Database)​ :定期将内存数据快照写入磁盘(通过save配置触发,如save 900 1表示900秒内至少1次修改则触发)。优点是文件紧凑、恢复快;缺点是可能丢失最后一次快照后的数据。
  • ​AOF(Append Only File)​ :记录所有写操作命令(追加到文件),重启时重新执行命令恢复数据。支持always(每条命令同步)、everysec(每秒同步,默认)、no(由操作系统决定)三种同步策略。优点是数据安全性高(最多丢失1秒数据);缺点是文件体积大,恢复速度慢。
(2)单线程模型

Redis 6.0 前采用​​单线程处理命令​​(IO多路复用技术处理网络请求),避免了多线程上下文切换的开销。6.0 后引入多线程处理网络IO(仅负责接收/发送命令),但命令执行仍由主线程完成,保证了原子性。

(3)IO多路复用

通过epoll/kqueue等系统调用,监听多个客户端连接,实现单线程高效处理大量并发请求。

1.3 Redis 数据类型

Redis 支持以下核心数据类型(均基于键值对存储,键为字符串):

数据类型 描述 典型应用场景
​String​ 字符串(支持整数、浮点数、二进制数据,最大512MB) 缓存、计数器、分布式锁
​Hash​ 键值对集合(类似Java的HashMap 存储对象(如用户信息user:1001
​List​ 有序可重复的列表(基于双向链表) 消息队列、历史记录
​Set​ 无序唯一的集合(基于哈希表或跳表) 去重、共同好友、随机抽取
​Sorted Set​ 有序唯一的集合(元素关联分数score,按分数排序) 排行榜、时间线
​Bitmap​ 基于String的位操作(每一位表示一个布尔值) 统计活跃用户、签到记录
​HyperLogLog​ 基于概率算法的统计结构(误差约0.81%) 统计海量数据的独立总数(如UV)
​Geo​ 地理位置存储(经纬度) 附近的人/地点查询

二、Redis 缓存增删改查实例(Python实现)

2.1 环境准备
  • 安装Redis服务(本地或远程,本文假设本地运行在localhost:6379);
  • 安装Python Redis客户端:pip install redis
2.2 业务场景

以"用户信息缓存"为例,实现以下功能:

  • ​增加缓存​:用户注册时,将用户信息存入Redis;
  • ​查询缓存​:用户登录时,优先从Redis获取信息;
  • ​修改缓存​:用户信息更新时,同步更新Redis;
  • ​删除缓存​:用户注销时,删除Redis中的缓存。
2.3 代码实现
复制代码
import redis

class RedisCache:
    def __init__(self, host='localhost', port=6379, db=0, password=None):
        self.redis_client = redis.Redis(
            host=host,
            port=port,
            db=db,
            password=password,
            decode_responses=True  # 自动解码字节为字符串
        )

    # 增加缓存(用户信息)
    def add_user_cache(self, user_id, user_info):
        """将用户信息以Hash形式存入Redis"""
        key = f"user:{user_id}"
        # user_info格式:{"name": "张三", "age": 25, "email": "zhangsan@example.com"}
        return self.redis_client.hset(key, mapping=user_info)

    # 查询缓存(用户信息)
    def get_user_cache(self, user_id):
        """从Redis获取用户信息"""
        key = f"user:{user_id}"
        user_data = self.redis_client.hgetall(key)
        return user_data if user_data else None  # 无缓存返回None

    # 修改缓存(用户信息)
    def update_user_cache(self, user_id, updated_info):
        """更新用户信息(仅更新存在的字段)"""
        key = f"user:{user_id}"
        if self.redis_client.exists(key):
            return self.redis_client.hupdate(key, mapping=updated_info)
        else:
            raise ValueError(f"用户{user_id}缓存不存在")

    # 删除缓存(用户信息)
    def delete_user_cache(self, user_id):
        """删除用户缓存"""
        key = f"user:{user_id}"
        return self.redis_client.delete(key)

# 示例用法
if __name__ == "__main__":
    # 初始化缓存客户端
    cache = RedisCache()

    # 1. 增加缓存:用户注册
    user_info = {"name": "张三", "age": 25, "email": "zhangsan@example.com"}
    cache.add_user_cache(user_id=1001, user_info=user_info)
    print("添加缓存成功,用户1001信息:", cache.get_user_cache(1001))

    # 2. 查询缓存:用户登录
    cached_user = cache.get_user_cache(1001)
    print("查询缓存结果:", cached_user)

    # 3. 修改缓存:用户信息更新(年龄改为26)
    updated_info = {"age": 26}
    cache.update_user_cache(user_id=1001, updated_info=updated_info)
    print("修改后缓存信息:", cache.get_user_cache(1001))

    # 4. 删除缓存:用户注销
    cache.delete_user_cache(1001)
    print("删除后缓存信息:", cache.get_user_cache(1001))  # 应返回None

三、使用Redis实现缓存并统计点击量

3.1 业务场景

统计某个页面(如商品详情页)的点击量,要求:

  • 实时性:每次点击立即更新计数;
  • 高并发:支持大量用户同时点击;
  • 持久化:重启后数据不丢失。
3.2 实现方案

使用Redis的​​String类型​ ​配合INCR命令实现计数器。INCR是原子操作,保证高并发下的正确性;结合持久化机制(如RDB/AOF)确保数据不丢失。

3.3 代码实现
复制代码
import redis
from datetime import datetime

class ClickCounter:
    def __init__(self, host='localhost', port=6379, db=0):
        self.redis_client = redis.Redis(host=host, port=port, db=db, decode_responses=True)

    # 记录一次点击(按页面和日期分组)
    def record_click(self, page_id):
        # 键格式:click:page:{page_id}:{date}(如click:page:101:20250808)
        today = datetime.now().strftime("%Y%m%d")
        key = f"click:page:{page_id}:{today}"
        return self.redis_client.incr(key)  # 原子递增,返回当前总次数

    # 获取某页面今日点击量
    def get_today_clicks(self, page_id):
        today = datetime.now().strftime("%Y%m%d")
        key = f"click:page:{page_id}:{today}"
        return int(self.redis_client.get(key) or 0)  # 无数据返回0

    # 获取某页面历史总点击量(可选:按日期聚合)
    def get_total_clicks(self, page_id):
        # 匹配所有日期的键(如click:page:101:*)
        keys = self.redis_client.keys(f"click:page:{page_id}:*")
        total = 0
        for key in keys:
            total += int(self.redis_client.get(key))
        return total

# 示例用法
if __name__ == "__main__":
    counter = ClickCounter()

    # 模拟用户点击商品详情页(page_id=101)
    for _ in range(5):
        counter.record_click(page_id=101)
    
    print("今日点击量(101页):", counter.get_today_clicks(101))  # 输出5
    print("历史总点击量(101页):", counter.get_total_clicks(101))  # 输出5(假设仅今日有数据)

四、总结

  • Redis 是高性能内存数据库,核心优势在于内存存储、多数据结构和持久化;
  • 缓存设计需考虑增删改查的原子性及与数据库的一致性;
  • 点击量统计利用String的INCR命令实现高效计数,支持高并发场景。