Redis概述

本文详细介绍了Redis基于内存的高效特性,包括其单线程设计、多线程IO处理、数据结构如string、set、zset和hash的应用场景,以及RDB和AOF两种持久化策略。此外,还讨论了事务处理和Redis的高可用性解决方案,如主从模式、哨兵模式和集群模式,以及如何应对缓存问题。

Redis基础

Redis 是基于内存运行的高性能K-V数据库

1. Redis为什么快

  1. 基于内存

  2. 单线程,减少上下文的切换,同事保证原子性(redis6+ 可开启多线程)

    1. 开启方式,非必要不开启
    2. 命令执行依旧由主线程负责
    3. 多线程只是负责 io 部分
    io-threads-do-reads yes  #开启IO线程
    io-threads 6    # 设置IO线程数
  3. IO多路复用(epoll, 非阻塞IO)

  4. 文件事件处理器(Reactor模式)

graph LR subgraph socket客户端 s1(socket) s2(socket) s(...) sn(socket) end io(io多路复用) s1-->io s2-->io s-->io sn-->io io-->queue(队列) queue-->dispatch(文件事件分派器) subgraph 事件处理器 cmd1(命令请求处理器) cmd2(命令请求处理器) cmd3(命令请求处理器) cmd(...) end dispatch--->cmd1 dispatch--->cmd2 dispatch--->cmd3 dispatch--->cmd

io多路复用会同时监听多个套接字,当监听的套接字准备好执行accept,read,write,close等操作时,就会产生相应的文件事件,io多路复用程序会将所有产生事件的套接字都压入一个队列,然后有序的每次仅一个套接字的方式传递给文件事件分派器,文件事件分派器接收到套接字后会根据套接字产生的事件类型调用对应的时间处理器.

2. Redis数据基础数据类型

  • string: 一个键对应一个值 (set k v), 内部维护的是一个动态字符串 SDS (Simple Dyamic String)
  • set: 是string字符串类型的无序集合,也不可重复(sadd key member)
  • zset: 与set类似,但是会关联一个double类型分数用来排序 (zadd key score member)
  • hash: 类似java的map,键值对集合,适合存储对象,可针对某一个属性进行修改
  • list: 列表,双向链表,可用来实现队列和栈的效果

3. 场景分析

根据不通的场景选择合适的数据类型

3.1 string应用场景

当字符串长度小于1MB, 每次扩容加倍. 大于1MB是,每次扩容1MB

  • 常规的 key-value缓存
  • 计数(incr, decr, incrby, decrby), 阅读量,粉丝数等等

3.2 set应用场景

set 类似于 list, 但是会重拍顺序,并且保证内部元素是不重复的

  • 做集合的交集,并集,差集操作, 张三的好友列表放在 key1, 李四好友 key2, sinterstore key3 key1 key2, 则key3为两人的共同好友
  • 抽奖功能,首页随机展示广告. spop, 将所有人的编号放在set中,通过 spop 随机取出一个元素
  • 并集统计. 公共活动A参加的人放在集合 key1, 参加活动B的放在key2, 获取所有参加了活的人. sumionstore key3 key1 key2, key3则是参加了活动的所有人

3.3 zset应用场景

与set相比,多了一个 score 权重属性,可按照 score 排序

  • 排行榜: 考试成绩排名, 直播在线人数排行,礼物排行榜等等

3.4 hash应用场景

内部是一个 field <-> value 的映射

  • 存储人员或者商品的信息: 通过 hset 修改某一个属性,而不用全部拿出来
  • 购物车: key用户, field商品ID, value 数量
  • 存储一些实时统计信息. 终端设备的电量,里程,存储量等各种统计信息,分别在不同的协议上报上来,可通过 hset 修改对应的值,并通过 hgetall 将信息全部拿出来

3.5 list应用场景

双向链表

  • 队列, A服务通过 rpush尾部压入数据, B服务通过 lpop从头部拿数据
  • 下拉分页的效果: lrange

4. Redis持久化方案

redis是内存数据库,宕机后数据会消失,因此需要将内存的数据持久化到磁盘,启动时恢复数据, redis有两种持久化方案,分别是 RDBAOF.

4.1 RDB(Redis DataBase)

默认的存储方式, RDB是通过快照的方式完成的,它保存的是某一时刻的数据信息.

save "" #关闭RDB功能

save 3600 1 #1小时内有一次变更则进行快照
save 300 10 #300秒内有10次变更则进行快照
save 60 10000  #1分钟内有1万次变更进行快照

可手动触发, 执行save阻塞备份或者 bgsave后台备份

graph TB bgsave-->父进程 A{是否有其他子进程在处理持久化} 父进程-->A A--是-->直接返回,不出来 A--否-->B(fork子进程,阻塞) B-->输出Backgroud_saving_started,并不在阻塞,响应其他命令 B..->子进程 子进程-->C[[生成RDB文件,并替换原有的RDB文件]] 子进程--信号通知父进程生成完毕-->父进程
优点
  • RDB是二进制的快照,占用空间小,方便传输(slave)
  • 使用子进程处理持久化操作,提高redis性能
  • RDB格式回复快
缺点
  • 不能保证数据完整性,丢失快照后的数据
  • 主进程数据量大的时候, fork子进程时阻塞时间会比较久

4.2 AOF(append only file)

默认情况下不开启, 开启后redis会将所有的写入命令写入到aof文件中,记录一个过程,恢复时,按照顺序执行即可

appendonly yes # 开启aof
dir . #存储aof问价的位置
appendfilename  appendonly.aof  # 文件名

# aof重写
auto-aof-rewrite-percentage 100   #当前文件大小超过上次AOF文件大小(启动时aof文件大小)百分比的时候重写
auto-aof-rewrite-min-size 64mb  #文件小于64MB的时候,不需要重写

# 手动通过命令 `bgrewriteaof` 进行重写

AOF重写后,大大缩小了文件的体积. 只包含了恢复当前数据的所需的最小命令集合.

收到重写信令 -> fork子进程携带主进程的数据副本->开启AOF重写缓存 -> 子进程完成重写 -> AOF重写缓存写入到新的AOF文件 -> 覆盖旧的AOF文件.

graph TB A((客户端)) A--命令请求-->服务器 服务器--命令内容-->现有AOF文件 服务器--命令内容-->AOF重写缓存
优点
  1. 一般每隔1秒,后台线程执行一次同步操作,丢失的数据会比较少
  2. 可读性强, 例如误操作了 flushall, 再没有发生 rewrite,可将aof中最后的 flushall删除, 恢复数据
缺点
  1. 文件大,恢复缓慢
  2. redis性能会下降,会频繁的写AOF文件

4.3 混合持久化

aof-use-db-preamble yes

文件的开头是 RBD格式的, 文件后面是 AOF 格式. 发生在 AOF 重写的时候.

5. 事务

  • multi 开始事务, 命令会放入队列
  • exce 执行事务中的所有操作
  • discard 取消事务
  • watch 监视一个或者多个key, 执行前,key被修改则中断(discard)
  • unwatch: 取消watch所有的key的监视

redis的事务是非原子性的,在一次执行ABC命令, 如果B发生类型错误,AC还是会执行的, 但是如果B发生语法错误,那么入队列的时候就发现了,ABC都不会执行. sets a b 这种就是语法错误, lpush a b, a不是一个list结构时.

完整用法

watch balance  # 监听余额

multi  #开启事务
decrby blance 20  #余额减20
incrby blance 40  #余额加40
exce  #提交事务
unwatch   # 取消监听

如果在执行事务 exce前, balance 被另外的线程修改, 那么exec会返回 '(nil)' 执行失败,事务回滚,整个都不执行.

6. Redis高可用

主从模式, 哨兵模式, 集群模式

6.1 主从模式

1住多从

  • 主机具有读写能力,从机读
sequenceDiagram title: 主从复制 从服务器 ->> 主服务器: SYNC请求 note over 主服务器: 创建快照 loop 主服务器 -->> 主服务器: 缓冲快照生成期间的写命令 end 主服务器 ->> 从服务器: 同步快照 note over 从服务器: 载入,解析快照 loop 主服务器 -->> 主服务器: 缓冲快照生成期间的写命令 end 主服务器 ->> 从服务器: 同步写缓冲 note over 从服务器: 载入缓冲 loop 主服务器->>从服务器: 增量同步 end

6.2 哨兵模式

主从模式下,当master宕机后,需要手动把从机切换到master, 而哨兵模式会自动选举,将其中一个slave作为新的master.

哨兵自己也可以进行集群,一般为基数个

graph LR subgraph 哨兵集群 sentiner1 sentiner2 sentiner3 end subgraph 主从节点 master-->slave1 master-->slave2 master-->slave3 end sentiner1-.1.->master sentiner1-.1.->slave1 sentiner1-.1.->slave2 sentiner1-.1.->slave3 sentiner2-.2.->master sentiner2-.2.->slave1 sentiner2-.2.->slave2 sentiner2-.2.->slave3 sentiner3-.3.->master sentiner3-.3.->slave1 sentiner3-.3.->slave2 sentiner3-.3.->slave3

6.3 集群模式(cluster模式)

哨兵模式下, 已经是高可用状态,但是他有一个严重的缺陷,就是所有机器的数据都是一样,极大的浪费内存. Redis 采用的是 slot 插槽的方式,将不通的数据存储到不通的机器上,一共 16383个插槽.

graph TB subgraph 客户端 client1 client2 end client1 -.-> RedisClusterDrive client2 -.-> RedisClusterDrive subgraph cluster master1 master2 master3 master1-->slave1 master2-->slave2 master3-->slave13 end RedisClusterDrive-.->master1 RedisClusterDrive-.->master2 RedisClusterDrive-.->master3

缓存问题

  • 缓存穿透: 大量请求根本不存在的key ==》 1. 空值设置短期有效期, 2. 布隆过滤器
  • 缓存击穿:热点数据突然过期,大量请求进入了redis。 ==》 1. 设置永久有效, 2. 定时任务来刷新过期时间, 3. 客户端设置互斥锁
  • 缓存雪崩:大量的redis中的key集体过期。 ==》 1. key的有效期尽量分散一点, 2. 数据预加载,在预测到大量并发前期,预缓存所有数据, 3.redis高可用,哨兵和集群(cluster)模式
### Redis 概述 Redis 是一种开源的、高性能的内存型键值存储系统,支持多种数据结构的操作。它不仅可以用作数据库,还可以作为缓存和消息中间件使用。Redis 的设计目标是提供极高的性能和丰富的功能,适用于各种需要高速数据访问的应用场景。 #### Redis 的基本特点 - **高性能**:由于其基于内存的数据存储机制,Redis 提供了非常低的延迟和高吞吐量。 - **持久化能力**:尽管 Redis 主要是一个内存数据库,但它也提供了两种持久化选项——RDB(快照)和 AOF(追加日志),从而能够在重启后恢复数据[^1]。 - **丰富的数据类型**:Redis 支持五种主要的数据类型,分别是字符串 (String)、哈希 (Map)、列表 (List)、集合 (Set) 和有序集合 (Sorted Set)[^3]。 - **主从复制**:通过主从复制技术,Redis 实现了数据冗余和服务可靠性,同时也为负载均衡奠定了基础。 --- ### Redis 的用途 Redis 被广泛应用于以下几个领域: 1. **缓存**:利用 Redis 的高性能特性,它可以作为一个高效的缓存层来加速 Web 应用程序中的频繁读取操作。 2. **消息队列**:Redis 可以充当发布/订阅模式的消息代理,也可以通过 List 类型实现简单的 FIFO 队列。 3. **实时分析**:借助于 Redis 对复杂数据类型的原生支持,可以轻松完成诸如计数器统计、排行榜维护等功能。 4. **分布式锁**:Redis 提供了一套原子性的命令集,使得开发者能够方便地构建跨进程甚至跨机器的同步控制逻辑。 5. **Session 存储**:Web 开发者经常把用户的 session 数据保存在 Redis 中以便提高响应速度并减少磁盘 I/O 压力。 --- ### Redis 的基本工作原理 #### 1. 内存存储模型 Redis 将所有的数据都加载到内存中进行处理,这极大地提升了它的运行效率。然而为了防止意外断电等情况造成数据丢失,Redis 还引入了 RDB 和 AOF 两种不同的持久化策略。 - **RDB(Redis Database Backup Process)**:定期创建时间点上的二进制文件来进行全量备份。 - **AOF(Append Only File)**:记录每次写入操作的具体指令序列,在必要时可以通过重放这些指令重新构造整个数据库状态。 #### 2. 主从架构下的扩展性 为了让单一实例具备更高的可用性和更大的容量上限,Redis 设计了一个灵活的主从复制框架。在这种体系下,主节点负责接收客户端发起的所有修改请求并将变更传播给若干个只读副本;而后者则可用于分流查询流量或参与更复杂的集群配置之中。 另外值得注意的是,当面对更加庞大的规模需求时,我们还能进一步采用 Redis Cluster 技术方案。该方法允许我们将原本集中管理的一整套 key-value 映射拆分成多个独立分区分别托管于不同物理设备之上,进而突破单机硬件资源瓶颈的同时保持良好的兼容性表现[^2]。 #### 3. 缓存优化技巧 针对实际生产环境中可能出现的各种异常状况比如缓存穿透、击穿等问题,也有相应的解决办法被提出并实践验证有效。例如可以在 API 层面加入额外的安全检测措施阻止恶意试探行为发生;或者运用像布隆过滤器这样的概率论工具提前甄别非法输入项等等[^4]。 #### 4. 性能监控与调整 最后不得不提一下关于如何保障长期稳定运转方面的话题。Slow Log 功能可以帮助管理员识别那些耗时过长影响整体效能的关键事务链路,并据此作出针对性改进决策。与此同时合理规划 Slow Query Logs 的保留长度也是维持良好运维体验不可或缺的一部分内容之一[^5]。 ```python import redis # 创建 Redis 客户端连接对象 r = redis.Redis(host='localhost', port=6379, db=0) # 设置一个键值对 r.set('name', 'Alice') # 获取指定键对应的值 value = r.get('name') print(value.decode()) # 输出 Alice ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值