Redis小学习
01.Redis是什么
Redis(Remote Dictionary Server)是一个开源的内存数据存储系统,也被称为数据结构服务器。它提供了一个键值存储数据库,并支持多种数据结构,如字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)等。
Redis以内存为主存储方式,但也可以将数据持久化到磁盘中,以实现数据的持久化存储。它具有高性能、高可用性和丰富的功能,被广泛应用于缓存、消息队列、实时统计分析、任务队列等场景。
Redis是一个功能强大、性能优越的内存数据存储系统,被广泛应用于各种分布式系统和高性能应用中。它提供了丰富的数据结构和功能,使得开发者可以更方便地构建高性能、可靠性和可伸缩性的应用系统。
1.1为什么需要Redis
- 数据从单表,演进出了分库分表MySQL从单机演进出了集群 数据量增长 读写数据压力的不断增加
- 数据分冷热 热数据:经常被访问到的数据 将热数据存储到内存中
Redis的主要原因是其高性能和低延迟的特点。由于Redis将数据存储在内存中,可以实现快速的数据读写操作,适用于需要快速响应和高并发访问的场景。此外,Redis还提供了丰富的数据结构和功能,如缓存、会话管理、消息队列等,使得开发者能够更方便地构建高性能、可靠性和可扩展性的应用系统。
1.2Redis的基本工作原理
-
数据从内存中读写 数据保存到硬盘上防止重启数据丢失 增量数据保存到AOF文件
全量数据RDB文件
单线程处理所有操作命令
-
Redis的基本工作原理可以简单概括为以下几个步骤:
- 客户端与Redis服务器建立连接:客户端通过网络连接到Redis服务器,建立起通信通道。
- 客户端发送命令请求:客户端向Redis服务器发送各种命令请求,如GET、SET等,以及相应的参数。
- Redis服务器执行命令操作:Redis服务器接收到客户端的命令请求后,根据请求的类型和参数执行相应的操作,如读取、写入、删除等。
- Redis服务器返回响应结果:执行命令操作后,Redis服务器将操作结果返回给客户端,如获取到的值、执行状态等。
- 客户端处理响应结果:客户端接收到Redis服务器返回的响应结果后,根据需要进行处理,如解析数据、错误处理等。
需要注意的是,Redis是单线程的,这意味着Redis服务器在任意时刻只能处理一个命令请求。为了提高并发性能,Redis采用了多路复用的机制,通过监听多个客户端连接,使用事件循环来处理客户端请求,实现高并发处理能力。
02.Redis应用案例
2.1Redis的实际应用场景
-
连续签到:
掘金每日连续签到 用户每日有一次签到的机会,如果断签,连续签到计数将归0。连续签到的定义:每天必须在23:59:59前签到 . Key: cc_uid_1165894833417101value: 252 expireAt:后天的0点
(String数据结构 数据结构- sds 可以存储字符串、数字、二进制数据·通常和expire配合使用 ·场景:存诸计数、session)
-
消息通知:
用list作为消息队列 使用场景:消息通知。 例如当文章更新时,将更新后的文章推送到ES,用户就能搜索到最新的文章数据
(List数据结构Quicklist Quicklist由一个双向链表和listpack实现)
(Listpack数据结构)
-
计数: 一个用户有多项计数需求,可通过hash结构存储
(Hash数据结构dict rehash: rehash操作是将ht[0]中的数据,全部迁移到ht[1]中。数据量小的场景下,直接将数据从ht[O]拷贝到ht[1]速度是较快的。数据量大的场景,例如存有上百万的KV时,迁移过程将会明显阻塞用户请求。 渐进式rehash:为避免出现这种情况,使用了rehash方案。基本原理就是,每次用户访问时都会迁移少量数据。将整个迁移过程,平摊到所有的访问用不请求过程中。)
-
排行榜
积分变化时,排名要实时变更 ·结合dict后,可实现通过key操作跳表的功能 ZINCRBY myzset 2 "Alex" ZSCORE myzset "Alex"
(zset数据结构zskiplist查找数字7的路径,head,3,3,7 结合dict后,可实现通过key操作跳表的功能 ZINCRBY myzset 2 "Alex"
ZSCORE myzset "Alex"
)
-
限流:
·要求1秒内放行的请求为N,超过N则禁止访问 Key: comment_freq_limit_1671356046 对这个Key调用incr,超过限制N则禁止访问1671356046是当前时间戳
-
分布式锁
·要求1秒内放行的请求为N,超过N则禁止访问 Key: comment_freq_limit_1671356046 对这个Key调用incr,超过限制N则禁止访问1671356046是当前时间戳
Redis在实际应用中有广泛的应用场景,包括但不限于以下几个方面:缓存,会话管理,消息队列,实时统计和计数器,分布式锁,地理位置服务。总之,Redis的应用场景非常广泛,可以用于缓存、会话管理、消息队列、实时统计和计数器等方面,帮助开发者构建高性能、可靠性和可伸缩性的应用系统。
2.2Redis常用数据结构
Redis提供了多种数据结构,每种数据结构都有自己的特点和适用场景。以下是Redis常用的数据结构:
- 字符串(String):字符串是Redis最基本的数据结构,可以存储任意类型的数据,如数字、文本等。常用的操作包括设置值、获取值、增减操作等。
- 哈希(Hash):哈希是一个键值对的集合,类似于关联数组。哈希适用于存储和操作对象的属性,可以方便地进行增删改查操作。
- 列表(List):列表是一个有序的字符串集合,可以进行插入、删除、修改和遍历等操作。列表适用于实现队列、栈等数据结构,也可以用于实现简单的消息队列。
- 集合(Set):集合是一个无序的字符串集合,不允许重复元素。集合支持交集、并集、差集等操作,适用于去重、快速判断元素是否存在等场景。
- 有序集合(Sorted Set):有序集合是一个有序的字符串集合,每个成员都关联了一个分数(score),用于排序。有序集合支持根据分数范围获取成员、按照分数排序等操作,适用于排行榜、优先级队列等场景。
除了以上常用的数据结构,Redis还提供了一些特殊的数据结构和功能,如位图(Bitmap)、地理位置(Geo)、HyperLogLog、发布订阅等,可以根据具体的业务需求选择合适的数据结构。
03.Redis使用注意事项
3.1.大Key、热Key
3.1.1学习:
-
大Key的定义:
数据类型——String类型——Hash/Set/Zset/list等复杂数据结构类型 大Key标准——value的字节数大于10KB即为大key——元素个数大于5000个或总value字节数大于10MB即为大key
-
大Key的危害: 读取成本高 容易导致慢查询(过期、删除)主从复制异常,服务阻塞 无法正常响应请求
-
业务侧使用大Key的表现: 请求Redis超时报错
-
消除大Key的方法:
1.拆分: 将大key拆分为小key。例如一个String拆分成多个String 2.压缩 将value压缩后写入redis,读取时解压后再使用。压缩算法可以是gzip、snappy、lz4等。通常情况下,一个压缩算法压缩率高、则解压耗时就长。需要对实际数据进行测试后,选择一个合适的算法。 如果存储的是JSON字符串,可以考虑使用MessagePack进行序列化。
-
集合类结构hash、list、set、set (1)拆分:可以用hash取余、位掩码的方式决定放在哪个key中 (2)区分冷热:如榜单列表场景使用zset,只缓存前10页数据,后续数据走db
-
热Key的定义 用户访问一个Key的QPS特别高,导致Server实例出现CPU负载突增或者不均的情况。热key没有明确的标准,QPS超过500就有可能被识别为热Key
-
解决热Key的方法
1.设置Localcache 在访问Redis前,在业务服务侧设置Localcache,降低访问Redis的QPS。LocalCache中缓存过期或未命中,则从Redis中将数据更新到LocalCache。Java的Guava、Golang的Bigcache就是这类LocalCache
2拆分 将key,value这一个热Key复制写入多份,例如key1.value,key2value,访问的时候访问多个key,但value是同一个,以此将qps分散到不同实例上,降低负载。代价是,更新时需要更新多个key,存在数据短暂不一致的风险
3.使用Redis代理的热Key承载能力 字节跳动的Redis访问代理就具备热Key承载能力。本质上是结合了"热Key发现"、"LocalCache"两个功能
3.1.2总结:
- 大Key(Big Key):指的是存储在Redis中占用内存较大的Key。大Key可能会导致Redis的内存占用过高,影响系统的性能和稳定性。常见的大Key包括大字符串、大哈希、大列表等。处理大Key的方法包括:
- 对大Key进行分解,将其拆分为多个较小的Key,以减少每个Key的内存占用。
- 使用Redis的数据结构和命令,如分片列表(分割为多个小列表)、分片哈希(分割为多个小哈希)等。
- 热Key(Hot Key):指的是被频繁访问的Key。热Key可能会导致Redis的性能瓶颈,因为大量的请求集中在少数的Key上,增加了系统的负载和响应时间。处理热Key的方法包括:
- 使用缓存策略,将热Key的数据缓存到内存中,减少对后端存储的访问。
- 使用Redis的分片和集群功能,将热Key分散到不同的实例上,以提高系统的并发能力和负载均衡性。
- 使用Redis的持久化功能,将热Key的数据定期保存到磁盘上,以防止数据丢失。
3.2慢查询场景
3.1.1认识
慢查询是指在Redis中执行时间较长的查询操作。慢查询可能会导致系统响应变慢,影响用户体验。处理慢查询需要根据具体的业务场景和需求来选择合适的方法和策略。可以使用Redis的监控工具和慢查询日志来定位慢查询,并进行性能优化。此外,合理设计数据结构、使用缓存和持久化等技术手段也可以帮助提高查询性能。
3.2.2容易导致redis慢查询的操作
(1)批量操作一次性传入过多的key/value,如mset/hmset/sadd/zadd等O(n)操作 建议单批次不要超过100,超过100之后性能下降明显。 (2)zset大部分命令都是O(log(n)),当大小超过5k以上时,简单的zadd/zrem也可能导致慢查询
(3)操作的单个value过大,超过10KB。也即,避免使用大Key (4)对大key的delete/expire操作也可能导致慢查询,Redis4.0之前不支持异步删除unlink,大key删除会阻塞Redis
3.3缓存穿透、缓存雪崩
3.3.1认识:
缓存穿透和缓存雪崩是常见的缓存相关问题,可能导致缓存系统性能下降或不可用;处理缓存穿透和缓存雪崩需要综合考虑业务场景和需求,选择合适的方法和策略。合理设计缓存系统、设置合理的过期时间、使用限流和熔断等技术手段可以帮助解决这些问题。
3.3.2深入:
缓存穿透:热点数据查询绕过缓存,直接查询数据库 缓存雪崩:大量缓存同时过期 缓存穿透的危害: (1)查询一个一定不存在的数据 通常不会缓存不存在的数据,这类查询请求都会直接打到db,如果有系统bug或人为攻击, 那么容易导致db响应慢甚至宕机 (2)缓存过期时 在高并发场景下,一个热key如果过期,会有大量请求同时击穿至db,容易影响db性能和稳定。 同一时间有大量key集中过期时,也会导致大量请求落到db上,导致查询变慢,甚至出现db无法响应新的查询