数据库 Redis
2024-03-24 21:19:58 0 举报
AI智能生成
数据库 Redis
作者其他创作
大纲/内容
Redis (REmote DIctionary Server)是一个基于 C 语言开发的开源 NoSQL 数据库(BSD 许可)。
Redis 基于内存,内存的访问速度是磁盘的上千倍。
Redis 基于 Reactor 模式设计开发了一套高效的事件处理模型,主要是单线程事件循环和 IO 多路复用。
Redis 内置了多种优化过后的数据类型/结构实现,性能非常高。
快的原因
首选
Redis
分布式缓存最开始兴起的那会,比较常用的。
Memcached
针对现代应用程序负荷需求而构建的内存数据库,完全兼容 Redis 和 Memcached 的 API,迁移时无需修改任何代码,号称全世界最快的内存数据库。
Dragonfly
Redis 的一个高性能分支,专注于多线程、内存效率和高吞吐量。
KeyDB
腾讯开源,基于 RocksDB,兼容 Redis,但关注度不高。
Tendis
分布式缓存选型
都是基于内存的数据库,一般都用来当做缓存使用。
都有过期策略。
两者的性能都非常高。
共同点
Redis 支持更丰富的数据类型(支持更复杂的应用场景)。Memcached 只支持最简单的 k/v 数据类型。
Redis 支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,而 Memcached 把数据全部存在内存之中。
Redis 有灾难恢复机制。 因为可以把缓存中的数据持久化到磁盘上。
Redis 在服务器内存使用完之后,可以将不用的数据放到磁盘上。但是,Memcached 在服务器内存使用完之后,就会直接报异常。
Memcached 没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据;但是 Redis 目前是原生支持 cluster 模式的。
Memcached 是多线程,非阻塞 IO 复用的网络模型;Redis 使用单线程的多路 IO 复用模型。 (Redis 6.0 针对网络数据的读写引入了多线程)
Redis 支持发布订阅模型、Lua 脚本、事务等功能,而 Memcached 不支持。并且,Redis 支持更多的编程语言。
Memcached 过期数据的删除策略只用了惰性删除,而 Redis 同时使用了惰性删除与定期删除。
区别
Redis 和 Memcached
使用内存,访问速度非常快。
高性能
一般像 MySQL 这类的数据库的 QPS 大概都在 1w 左右(4 核 8g) ,但是使用 Redis 缓存之后很容易达到 10w+,甚至最高能达到 30w+(就单机 Redis 的情况,Redis 集群的话会更高)。
QPS(Query Per Second):服务器每秒可以执行的查询次数。
高并发
用 Redis 原因
服务端需要同时维系 db 和 cache,并且是以 db 的结果为准。
我们平时使用比较多的一个缓存读写模式,比较适合读请求比较多的场景。
写
读
首次请求数据一定不在 cache 的问题。解决:可以将热点数据可以提前放入 cache 中。
写操作比较频繁的话导致 cache 中的数据会被频繁被删除,这样会影响缓存命中率 。解决:数据库和缓存数据强一致场景:更新 db 的时候同样更新 cache,不过我们需要加一个锁/分布式锁来保证更新 cache 的时候不存在线程安全问题。可以短暂地允许数据库和缓存数据不一致的场景:更新 db 的时候同样更新 cache,但是给缓存加一个比较短的过期时间。
缺陷
Cache Aside Pattern(旁路缓存模式)
服务端把 cache 视为主要数据存储,从中读取数据并将数据写入其中。
在平时在开发过程中非常少见,因为 Redis 并没有提供 cache 将数据写入 db 的功能。
Read-Through Pattern 实际只是在 Cache-Aside Pattern 之上进行了封装。
写(Write Through)
读(Read Through)
Read/Write Through Pattern(读写穿透)
与 Read/Write Through Pattern 很相似,但其只更新缓存,不直接更新 db,而是改为异步批量的方式来更新 db。
在平时开发过程中也非常少见,因其更新db方式对数据一致性带来了更大的挑战。
消息队列中消息的异步写入磁盘、MySQL 的 Innodb Buffer Pool 机制。
db 的写性能非常高,非常适合一些数据经常变化又对数据一致性要求没那么高的场景,比如浏览量、点赞量。
应用
Write Behind Pattern(异步缓存写入)
读写策略
Redis 从 4.0 版本开始,支持通过 Module 来扩展其功能以满足特殊的需求。这些 Module 以动态链接库(so 文件)的形式被加载到 Redis 中。
实现搜索引擎、处理 JSON 数据、实现图形数据库、处理时间序列数据、实现布隆过滤器、实现分布式限流模块等等。
常用
模块化
分布式锁:通过 Redis 来做分布式锁是一种比较常见的方式。基于 Redisson 来实现分布式锁。
限流:一般是通过 Redis + Lua 脚本的方式来实现限流。
消息队列:Redis 自带的 List/Stream 数据结构可以作为一个简单的队列使用。不建议。
延时队列:Redisson 内置了延时队列(基于 Sorted Set 实现的)。
分布式 Session :利用 String 或者 Hash 数据类型保存 Session 数据,所有的服务器都可以访问。
复杂业务场景:通过 Redis 以及 Redis 扩展(比如 Redisson)提供的数据结构,我们可以很方便地完成很多复杂的业务场景。
RediSearch + RedisJSON 可实现小型项目的简单搜索场景。
比较复杂或者数据规模较大的搜索场景还是建议使用 Elasticsearch。
搜索引擎
5 种基础数据类型:String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset(有序集合)。
3 种特殊数据类型:HyperLogLog(基数统计)、Bitmap (位图)、Geospatial (地理位置)。
其它特殊数据类型:Bloom filter(布隆过滤器)、Bitfield(位域)。
基础数据类型的底层 8 种数据结构:简单动态字符串(SDS)、LinkedList(双向链表)、Dict(哈希表/字典)、SkipList(跳跃表)、Intset(整数集合)、ZipList(压缩列表)、QuickList(快速列表)。
概要
String 是 Redis 中最简单同时也是最常用的一个数据类型。
String 是一种二进制安全的数据类型,可以用来存储任何类型的数据比如字符串、整数、浮点数、图片(base64 编码或路径)、序列化后的对象。
简单动态字符串(Simple Dynamic String,SDS)
底层实现
常规数据(比如 Session、Token、序列化后的对象、图片的路径)的缓存。
计数比如用户单位时间的请求数(简单限流可以用到)、页面单位时间的访问数。
分布式锁(利用 SETNX key value 命令可以实现一个最简易的分布式锁)。
对象中某些字段需要经常变动或者经常需要单独查询对象中的个别字段信息,Hash 非常适合。
系统对性能和资源消耗非常敏感的话,String 非常适合。
在绝大部分情况,推荐使用 String 来存储对象数据。
与 Hash 对比
String(字符串)
Redis 的 List 的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。
LinkedList(双向链表)/ ZipList(压缩列表)/ QuickList(快速列表)
信息流展示(最新文章、最新动态)
消息队列,只是功能过于简单且存在很多缺陷,不建议这样做。
List(列表)
Redis 中的 Hash 是一个 String 类型的 field-value(键值对) 的映射表,特别适合用于存储对象。
Dict(哈希表/字典)、ZipList(压缩列表)
对象数据存储场景(用户信息、商品信息、文章信息、购物车信息)
Hash(哈希)
Redis 中的 Set 类型是一种无序集合,集合中的元素没有先后顺序但都唯一。
Dict(哈希表/字典)、Intset(整数集合)
需要存放的数据不能重复的场景(网站 UV 统计、文章点赞、动态点赞)
需要获取多个数据源交集、并集和差集的场景(共同好友(交集)、好友推荐(差集)、订阅号推荐(差集+交集))
需要随机获取数据源中的元素的场景(抽奖系统、随机点名)
Set(集合)
类似于 Set,但增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列,还可以通过 score 的范围来获取元素的列表。
ZipList(压缩列表)、SkipList(跳跃表)
需要随机获取数据源中的元素根据某个权重进行排序的场景(各种排行榜)
需要存储的数据有优先级或者重要程度的场景(优先级任务队列)
Sorted Set(有序集合)
Bitmap 存储的是连续的二进制数字(0 和 1),只需要一个 bit 位来表示某个元素对应的值或者状态,key 就是对应元素本身 。
需要保存状态信息(0/1 即可表示)的场景(用户签到情况、活跃用户情况、用户行为统计)
Bitmap (位图)
HyperLogLog 是一种有名的基数计数概率算法 ,Redis 只是实现了这个算法并提供了一些开箱即用的 API。
Redis 提供的 HyperLogLog 占用空间非常非常小,只需要 12k 的空间就能存储接近2^64个不同元素。
稀疏矩阵:计数较少的时候,占用空间很小。
稠密矩阵:计数达到某个阈值的时候,占用 12k 的空间。
计数方式
数量量巨大(百万、千万级别以上)的计数场景(热门网站每日/每周/每月访问 ip 数统计、热门帖子 uv 统计)
HyperLogLog(基数统计)
Geospatial index(地理空间索引,简称 GEO) 主要用于存储地理位置信息,基于 Sorted Set 实现。
通过 GEO 我们可以轻松实现两个位置距离的计算、获取指定位置附近的元素等功能。
需要管理使用地理空间数据的场景(附近的人)
Geospatial (地理位置)
数据类型
使用缓存的时候,我们经常需要对内存中的数据进行持久化也就是将内存中的数据写入到硬盘中。
快照(snapshotting,RDB)
只追加文件(append-only file,AOF)
RDB 和 AOF 的混合持久化(Redis 4.0 新增)
方式
Redis 可以通过创建快照来获得存储在内存里面的数据在 某个时间点 上的副本。默认方式。
将快照复制到其他服务器从而创建具有相同数据的服务器副本(Redis 主从结构,主要用来提高 Redis 性能)。
将快照留在原地以便重启服务器的时候使用。
save : 同步保存操作,会阻塞 Redis 主线程。
bgsave : fork 出一个子进程,子进程执行,不会阻塞 Redis 主线程,默认选项。
生成 RDB 快照命令
RDB 文件存储的内容是经过压缩的二进制数据, 保存着某个时间点的数据集,文件很小,适合做数据的备份,灾难恢复。
使用 RDB 文件恢复数据,直接解析还原数据即可,不需要一条一条地执行命令,速度非常快。
优势
RDB 文件是以特定的二进制格式保存的,并且在 Redis 版本演进中有多个版本的 RDB,所以存在老版本的 Redis 服务不兼容新版本的 RDB 格式的问题。
劣势
RDB 持久化
与快照持久化相比,AOF 持久化的实时性更好。默认情况下 Redis 没有开启 AOF(append only file)方式的持久化(Redis 6.0 之后已经默认是开启了)。
命令追加(append):所有的写命令会追加到 AOF 缓冲区中。
文件写入(write):将 AOF 缓冲区的数据写入到 AOF 文件中。
文件同步(fsync):AOF 缓冲区根据对应的持久化方式( fsync 策略)向硬盘做同步操作。
文件重写(rewrite):随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。
重启加载(load):当 Redis 重启时,可以加载 AOF 文件进行数据恢复。
write:写入系统内核缓冲区之后直接返回(仅仅是写到缓冲区),不会立即同步到硬盘。
fsync:用于强制刷新系统内核缓冲区(同步到到磁盘),确保写磁盘操作结束才会返回。
定义
流程
appendfsync always:write + fsync,这样会严重降低 Redis 的性能。
appendfsync everysec:write + fsync,fsync 间隔为 1 秒,兼顾数据和写入性能。
appendfsync no:write 但不 fsync,fsync 的时机由操作系统决定。
这 3 种持久化方式的主要区别在于 fsync 同步 AOF 文件的时机(刷盘)。
从 Redis 7.0.0 开始,Redis 使用了 Multi Part AOF 机制。顾名思义,Multi Part AOF 就是将原来的单个 AOF 文件拆分成多个 AOF 文件。在 Multi Part AOF 中,AOF 文件被分为三种类型,分别为:BASE:表示基础 AOF 文件,它一般由子进程通过重写产生,该文件最多只有一个。INCR:表示增量 AOF 文件,它一般会在 AOFRW 开始执行时被创建,该文件可能存在多个。HISTORY:表示历史 AOF 文件,它由 BASE 和 INCR AOF 变化而来,每次 AOFRW 成功完成时,本次 AOFRW 之前对应的 BASE 和 INCR AOF 都将变为 HISTORY,HISTORY 类型的 AOF 会被 Redis 自动删除。
方式( fsync策略)
避免额外的检查开销,AOF 记录日志不会对命令进行语法检查。
在命令执行完之后再记录,不会阻塞当前的命令执行。
如果刚执行完命令 Redis 就宕机会导致对应的修改丢失。
可能会阻塞后续其他命令的执行(AOF 记录日志是在 Redis 主线程中进行的)。
风险
执行完命令之后记录日志原因
当 AOF 变得太大时,Redis 在后台自动重写 AOF 产生一个新的 AOF 文件,新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样,但体积更小。
AOF 重写
Redis 在启动时对 AOF 文件进行检查,以判断文件是否完整,是否有损坏或者丢失的数据。
校验和(checksum),通过对整个 AOF 文件内容进行 CRC64 算法计算得出的数字。
原理
AOF 校验机制
RDB 的数据安全性不如 AOF,没有办法实时或者秒级持久化数据。
AOF 以一种易于理解和解析的格式包含所有操作的日志。
AOF 持久化
由于 RDB 和 AOF 各有优势,于是,Redis 4.0 开始支持 RDB 和 AOF 的混合持久化(默认关闭,可以通过配置项 aof-use-rdb-preamble 开启)。
混合持久化
Redis 保存的数据丢失一些也没什么影响的话,可以选择使用 RDB。
不建议单独使用 AOF,因为时不时地创建一个 RDB 快照可以进行数据库备份、更快的重启以及解决 AOF 引擎错误。
如果保存的数据要求安全性比较高的话,建议同时开启 RDB 和 AOF 持久化或者开启 RDB 和 AOF 混合持久化。
RDB 和 AOF
持久化
对于读写命令来说,Redis 一直是单线程模型。
Redis 4.0 版本之后引入了多线程来执行一些大键值对的异步删除操作。
Redis 6.0 版本之后引入了多线程来处理网络请求(提高网络 IO 读写性能)。
Redis 基于 Reactor 模式设计开发了一套高效的事件处理模型 ,该模型对应的是 Redis 中的文件事件处理器(file event handler)。
由于文件事件处理器(file event handler)是单线程方式运行的,所以一般都说 Redis 是单线程模型。
多个 socket(客户端连接)
IO 多路复用程序(支持多个客户端连接的关键)
文件事件分派器(将 socket 关联到相应的事件处理器)
事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
文件事件处理器
单线程模型
Redis6.0 虽然引入了多线程,但是只是在网络数据的读写这类耗时操作上使用,执行命令仍然是单线程顺序执行,因此不需要担心线程安全问题。
Redis6.0 的多线程默认是禁用的,只使用主线程。并且开启后,性能不能有太大提升,因此一般情况下并不建议开启。
用于执行一些比较耗时的操作。
通过 bio_close_file 后台线程来释放 AOF / RDB 等过程中产生的临时文件资源。
通过 bio_aof_fsync 后台线程调用 fsync 函数将系统内核缓冲区还未同步到到磁盘的数据强制刷到磁盘( AOF 文件)。
通过 bio_lazy_free 后台线程释放大对象(已删除)占用的内存空间。
后台线程
线程模型
Redis 通过一个叫做过期字典(可以看作是 hash 表)来保存数据过期的时间。
惰性删除:只会在取出 key 的时候才对数据进行过期检查。
定期删除:每隔一段时间抽取一批 key 执行删除过期 key 操作。
定期删除对内存更加友好,惰性删除对 CPU 更加友好。两者各有千秋,所以 Redis 采用的是 定期删除+惰性/懒汉式删除 。
过期数据的删除策略
解决可能存在定期删除和惰性删除漏掉了很多过期 key 的情况,导致大量过期 key 堆积在内存里而 Out of memory 问题。
内存淘汰机制
volatile-lru(least recently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰。
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰。
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰。
allkeys-lru(least recently used):当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)。
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰。
no-eviction:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。不推荐!
volatile-lfu(least frequently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰。
allkeys-lfu(least frequently used):当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的 key。
数据淘汰策略
内存管理
Redis 事务提供了一种将多个命令请求打包的功能。然后,再按顺序执行打包的所有命令,并且不会被中途打断。
Redis 可以通过 MULTI,EXEC,DISCARD 和 WATCH 等命令来实现事务(Transaction)功能。
Redis 事务是不支持回滚(roll back)操作,Redis 事务不满足原子性。
Redis 事务的持久性也是没办法保证。
通过 Lua 脚本来批量执行 Redis 命令实际也是不完全满足原子性的。
Redis 事务实际开发中使用的非常少,功能比较鸡肋,不建议在日常开发中使用。
事务
原生批量操作命令
pipeline(流水线)
Lua 脚本
使用批量操作减少网络传输
给 key 设置随机过期时间。推荐!
开启 lazy-free(惰性删除/延迟释放) 。lazy-free 特性是 Redis 4.0 开始引入的。
大量 key 集中过期问题
String 类型的 value 超过 1MB。
复合类型(List、Hash、Set、Sorted Set 等)的 value 包含的元素超过 5000 个。
标准
客户端超时阻塞、网络阻塞、工作线程阻塞
问题
使用 Redis 自带的 --bigkeys 参数来查找。
使用 Redis 自带的 SCAN 命令。
借助开源工具分析 RDB 文件。
借助公有云的 Redis 分析服务。
定位
分割 bigkey:将一个 bigkey 分割为多个小 key。
手动清理:Redis 4.0+ 可以使用 UNLINK 命令来异步删除一个或多个指定的 key。
采用合适的数据结构。
开启 lazy-free(惰性删除/延迟释放) :lazy-free 特性是 Redis 4.0 开始引入的。
处理
Redis bigkey(大 Key)
如果一个 key 的访问次数比较多且明显多于其他 key 的话,那这个 key 就可以看作是 hotkey(热 Key)。
处理 hotkey 会占用大量的 CPU 和带宽,可能会影响 Redis 实例对其他请求的正常处理。
如果突然访问 hotkey 的请求超出了 Redis 的处理能力,Redis 就会直接宕机。
使用 Redis 自带的 --hotkeys 参数来查找。
使用MONITOR 命令。
京东零售的 hotkey 项目。
借助开源项目。
根据业务情况提前预估。
业务代码中记录分析。
读写分离:主节点处理写请求,从节点处理读请求。
使用 Redis Cluster:将热点数据分散存储在多个 Redis 节点上。
二级缓存:hotkey 采用二级缓存的方式进行处理,将 hotkey 存放一份到 JVM 本地内存中(可以用 Caffeine)。
公有云,通过代理查询缓存功能(Proxy Query Cache)优化热点 Key 问题。
Redis hotkey(热 Key)
Redis 慢查询统计的是命令执行这一步骤的耗时,慢查询命令也就是那些命令执行时间较长的命令。
KEYS *:会返回所有符合规则的 key。
HGETALL:会返回一个 Hash 中所有的键值对。
LRANGE:会返回 List 中指定范围内的元素。
SMEMBERS:返回 Set 中的所有元素。
SINTER/SUNION/SDIFF:计算多个 Set 的交集/并集/差集。
时间复杂度 O(n) 的命令
ZRANGE/ZREVRANGE:返回指定 Sorted Set 中指定排名范围内的所有元素。
ZREMRANGEBYRANK/ZREMRANGEBYSCORE:移除 Sorted Set 中指定排名范围/指定 score 范围内的所有元素。
时间复杂度 O(n) 以上的命令
在 redis.conf 文件中,我们可以使用 slowlog-log-slower-than 参数设置耗时命令的阈值,并使用 slowlog-max-len 参数设置耗时命令的最大记录条数。
慢查询命令
那些不可用的空闲内存。虽然不会影响 Redis 性能,但是会增加内存消耗。
Redis 存储存储数据的时候向操作系统申请的内存空间可能会大于数据实际需要的存储空间。
频繁修改 Redis 中的数据也会产生内存碎片。
原因
使用 info memory 命令即可查看 Redis 内存相关的信息。
内存碎片率的计算公式:mem_fragmentation_ratio = used_memory_rss / used_memory
mem_fragmentation_ratio (内存碎片率)的值越大代表内存碎片率越严重。
mem_fragmentation_ratio > 1.5 才需要清理内存碎片。
查看
注意性能影响,可通过配置控制。
直接通过 config set 命令将 activedefrag 配置项设置为 yes 即可。
重启节点可以做到内存碎片重新整理。
清理
内存碎片
性能优化
大量请求的 key 是不合理的,根本不存在于缓存中,也不存在于数据库中 。
最基本的就是首先做好参数校验,一些不合法的参数请求直接抛出异常信息返回给客户端。
缓存无效 key、布隆过滤器、接口限流
解决
缓存穿透
请求的 key 对应的是 热点数据 ,该数据 存在于数据库中,但不存在于缓存中(通常是因为缓存中的那份数据已经过期) 。
设置热点数据永不过期或者过期时间比较长。
针对热点数据提前预热,将其存入缓存中并设置合理的过期时间比如秒杀场景下的数据在秒杀结束之前不过期。
请求数据库写数据到缓存之前,先获取互斥锁,保证只有一个请求会落到数据库上,减少数据库的压力。
缓存击穿
缓存在同一时间大面积的失效,导致大量的请求都直接落到了数据库上,对数据库造成了巨大的压力。
采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用。
限流,避免同时处理大量的请求。
多级缓存,例如:本地缓存 + Redis 缓存的组合。
服务不可用
设置不同的失效时间比如随机设置缓存的失效时间。
缓存永不失效(不太推荐,实用性太差)。
使用定时任务,比如 xxl-job。
使用消息队列,比如 Kafka。
缓存预热,也就是在程序启动后或运行过程中,主动将热点数据加载到缓存中。
热点缓存失效
缓存雪崩
O(n) 命令
SAVE 创建 RDB 快照、AOF 日志记录阻塞、AOF 刷盘阻塞、AOF 重写阻塞
大 Key、清空数据库、集群扩容、Swap(内存交换)、CPU 竞争、网络问题
Redis 阻塞
生产问题
Redis 集群是一种通过将多个 Redis 节点连接在一起以实现高可用性、数据分片和负载均衡的技术。
主要有三种模式:主从复制模式(Master-Slave)、哨兵模式(Sentinel)和 Cluster 模式。
高可用性:Redis集群可以在某个节点发生故障时,自动进行故障转移,保证服务的持续可用。
负载均衡:Redis集群可以将客户端请求分发到不同的节点上,有效地分摊节点的压力,提高系统的整体性能。
容灾恢复:通过主从复制或哨兵模式,Redis集群可以在主节点出现故障时,快速切换到从节点,实现业务的无缝切换。
数据分片:在Cluster模式下,Redis集群可以将数据分散在不同的节点上,从而突破单节点内存限制,实现更大规模的数据存储。
易于扩展:Redis集群可以根据业务需求和系统负载,动态地添加或移除节点,实现水平扩展。
作用
一种基本集群模式,它通过将一个Redis节点(主节点)的数据复制到一个或多个其他Redis节点(从节点)来实现数据的冗余和备份。
配置简单,易于实现。
实现数据冗余,提高数据可靠性。
读写分离,提高系统性能。
优点
主节点故障时,需要手动切换到从节点,故障恢复时间较长。
主节点承担所有写操作,可能成为性能瓶颈。
无法实现数据分片,受单节点内存限制。
缺点
数据备份和容灾恢复:通过从节点备份主节点的数据,实现数据冗余。
读写分离:将读操作分发到从节点,减轻主节点压力,提高系统性能。
在线升级和扩展:在不影响主节点的情况下,通过增加从节点来扩展系统的读取能力。
主从复制模式(Master-Slave)
在主从复制基础上加入了哨兵节点,实现了自动故障转移。
自动故障转移,提高系统的高可用性。
具有主从复制模式的所有优点,如数据冗余和读写分离。
配置和管理相对复杂。
依然无法实现数据分片,受单节点内存限制。
高可用性要求较高的场景:通过自动故障转移,确保服务的持续可用。
数据备份和容灾恢复:在主从复制的基础上,提供自动故障转移功能。
哨兵模式(Sentinel)
Redis的一种高级集群模式,它通过数据分片和分布式存储实现了负载均衡和高可用性。
在Cluster模式下,Redis将所有的键值对数据分散在多个节点上。每个节点负责一部分数据,称为槽位。
通过对数据的分片,Cluster模式可以突破单节点的内存限制,实现更大规模的数据存储。
Redis Cluster将数据分为16384个槽位,每个节点负责管理一部分槽位。
当客户端向Redis Cluster发送请求时,Cluster会根据键的哈希值将请求路由到相应的节点。
具体来说,Redis Cluster使用CRC16算法计算键的哈希值,然后对16384取模,得到槽位编号。
数据分片与槽位
数据分片,实现大规模数据存储。
负载均衡,提高系统性能。
自动故障转移,提高高可用性。
配置和管理较复杂。
一些复杂的多键操作可能受到限制。
大规模数据存储:通过数据分片,突破单节点内存限制。
高性能要求场景:通过负载均衡,提高系统性能。
高可用性要求场景:通过自动故障转移,确保服务的持续可用。
Cluster 模式
集群
使用连接池:避免频繁创建关闭客户端连接。
尽量不使用 O(n)指令,使用 O(n) 命令时要关注 n 的数量。
使用批量操作减少网络传输:原生批量操作命令(比如 MGET、MSET等等)、pipeline、Lua 脚本。
尽量不适用 Redis 事务:Redis 事务实现的功能比较鸡肋,可以使用 Lua 脚本代替。
禁止长时间开启 monitor:对性能影响比较大。
控制 key 的生命周期:避免 Redis 中存放了太多不经常被访问的数据。
规范
数据库 Redis
0 条评论
回复 删除
下一页