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

发布于:2025-08-10 ⋅ 阅读:(19) ⋅ 点赞:(0)

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

目录

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

1.1 Redis 概念

1.2 Redis 核心原理

(1)内存存储与持久化

(2)单线程模型

(3)IO多路复用

1.3 Redis 数据类型

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

2.1 环境准备

2.2 业务场景

2.3 代码实现

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

3.1 业务场景

3.2 实现方案

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命令实现高效计数,支持高并发场景。

网站公告

今日签到

点亮在社区的每一天
去签到