共计 15799 个字符,预计需要花费 40 分钟才能阅读完成。
Redis 简介
Redis 是一个应用 C 语言编写的,开源的(BSD 许可)高性能非关系型(NoSQL)的键值对数据库。
Redis 能够存储键和五种不同类型的值之间的映射。键的类型只能为字符串,值反对五种数据类型:字符串、列表、汇合、散列表、有序汇合。
与传统数据库不同的是 Redis 的数据是存在内存中的,所以读写速度十分快,因而 redis 被广泛应用于缓存方向,每秒能够解决超过 10 万次读写操作,是已知性能最快的 Key-Value DB。另外,Redis 也常常用来做分布式锁。除此之外,Redis 反对事务、长久化、LUA 脚本、LRU 驱动事件、多种集群计划(Redis 6.0 集群搭建实际)。
从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 资助。
Redis 的优缺点
长处
- 读写性能优异,Redis 能读的速度是 110000 次 /s,写的速度是 81000 次 /s。
- 反对数据长久化,反对 AOF 和 RDB 两种长久化形式。
- 反对事务,Redis 的所有操作都是原子性的,同时 Redis 还反对对几个操作合并后的原子性执行。
- 数据结构丰盛,除了反对 string 类型的 value 外还反对 hash、set、zset、list 等数据结构。
- 反对主从复制,主机会主动将数据同步到从机,能够进行读写拆散。
毛病
- 数据库容量受到物理内存的限度,不能用作海量数据的高性能读写,因而 Redis 适宜的场景次要局限在较小数据量的高性能操作和运算上。
- Redis 不具备主动容错和复原性能,主机从机的宕机都会导致前端局部读写申请失败,须要期待机器重启或者手动切换前端的 IP 能力复原。
- 主机宕机,宕机前有局部数据未能及时同步到从机,切换 IP 后还会引入数据不统一的问题,升高了零碎的可用性。
- Redis 较难反对在线扩容,在集群容量达到下限时在线扩容会变得很简单。为防止这一问题,运维人员在零碎上线时必须确保有足够的空间,这对资源造成了很大的节约。
数据类型
Redis 次要有 5 种数据类型,包含 String,List,Set,Zset,Hash,满足大部分的应用要求。具体的可参考:Redis 的 8 大数据类型,写得十分好!
应用场景
因为 Redis 优异的读写性能,长久化反对等劣势,Redis 的应用场景十分多,次要包含计数器,缓存,音讯队列,分布式锁等,具体应用场景如下:
-
计数器
- 能够对 String 进行自增自减运算,从而实现计数器性能。
- Redis 这种内存型数据库的读写性能十分高,很适宜存储频繁读写的计数量。
-
缓存
- 将热点数据放到内存中,设置内存的最大使用量以及淘汰策略来保障缓存的命中率。
-
会话缓存
- 能够应用 Redis 来对立存储多台应用服务器的会话信息。
- 当应用服务器不再存储用户的会话信息,也就不再具备状态,一个用户能够申请任意一个应用服务器,从而更容易实现高可用性以及可伸缩性。
-
全页缓存(FPC)
- 除根本的会话 token 之外,Redis 还提供很简便的 FPC 平台。
- 以 Magento 为例,Magento 提供一个插件来应用 Redis 作为全页缓存后端。此外,对 WordPress 的用户来说,Pantheon 有一个十分好的插件 wp-redis,这个插件能帮忙你以最快速度加载你曾浏览过的页面。
-
查找表
- 例如 DNS 记录就很适宜应用 Redis 进行存储。
- 查找表和缓存相似,也是利用了 Redis 疾速的查找个性。然而查找表的内容不能生效,而缓存的内容能够生效,因为缓存不作为牢靠的数据起源。
-
音讯队列(公布 / 订阅性能)
- List 是一个双向链表,能够通过 lpush 和 rpop 写入和读取音讯
- 不过最好应用 Kafka、RabbitMQ 等消息中间件。
-
分布式锁实现
- 在分布式场景下,无奈应用单机环境下的锁来对多个节点上的过程进行同步。
- 能够应用 Redis 自带的 SETNX 命令实现分布式锁,除此之外,还能够应用官网提供的 RedLock 分布式锁实现。
-
其它
- Set 能够实现交加、并集等操作,从而实现独特好友等性能。
- ZSet 能够实现有序性操作,从而实现排行榜等性能。
长久化
Redis 是内存型数据库,为了之后重用数据(比方重启机器、机器故障之后回复数据),或者是为了避免系统故障而将数据备份到一个近程地位,须要将内存中的数据长久化到硬盘上。
Redis 提供了 RDB 和 AOF 两种长久化形式。默认是只开启 RDB,当 Redis 重启时,它会优先应用 AOF 文件来还原数据集。
Redis 长久化详解能够参考:Redis 长久化
过期键的删除策略
Redis 中有个设置工夫过期的性能,即对存储在 redis 数据库中的值能够设置一个过期工夫。作为一个缓存数据库,这是十分实用的。如咱们个别我的项目中的 token 或者一些登录信息,尤其是短信验证码都是有工夫限度的,依照传统的数据库解决形式,个别都是本人判断过期,这样无疑会重大影响我的项目性能。
Redis 有三种不同的删除策略:立刻删除,惰性删除,定时删除
- (1):立刻删除。在设置键的过期工夫时,创立一个回调事件,当过期工夫达到时,由工夫处理器主动执行键的删除操作。
- (2):惰性删除。键过期了就过期了,不论。每次从 dict 字典中按 key 取值时,先查看此 key 是否曾经过期,如果过期了就删除它,并返回 nil,如果没过期,就返回键值。
- (3):定时删除。每隔一段时间,对 expires 字典进行查看,删除外面的过期键。
能够看到,第二种为被动删除,第一种和第三种为被动删除,且第一种实时性更高。上面对这三种删除策略进行具体分析。
- 立刻删除
立刻删除能保障内存中数据的最大新鲜度,因为它保障过期键值会在过期后马上被删除,其所占用的内存也会随之开释。然而立刻删除对 cpu 是最不敌对的。因为删除操作会占用 cpu 的工夫,如果刚好碰上了 cpu 很忙的时候,比方正在做交加或排序等计算的时候,就会给 cpu 造成额定的压力。
而且目前 redis 事件处理器对工夫事件的解决形式–无序链表,查找一个 key 的工夫复杂度为 O(n), 所以并不适宜用来解决大量的工夫事件。
- 惰性删除
惰性删除是指,某个键值过期后,此键值不会马上被删除,而是等到下次被应用的时候,才会被查看到过期,此时能力失去删除。所以惰性删除的毛病很显著: 节约内存。dict 字典和 expires 字典都要保留这个键值的信息。
举个例子,对于一些按工夫点来更新的数据,比方 log 日志,过期后在很长的一段时间内可能都得不到拜访,这样在这段时间内就要拜拜节约这么多内存来存 log。这对于性能十分依赖于内存大小的 redis 来说,是比拟致命的。
- 定时删除
从下面剖析来看,立刻删除会短时间内占用大量 cpu,惰性删除会在一段时间内节约内存,所以定时删除是一个折中的方法。
定时删除是:每隔一段时间执行一次删除操作,并通过限度删除操作执行的时长和频率,来缩小删除操作对 cpu 的影响。另一方面定时删除也无效的缩小了因惰性删除带来的内存节约。
- Redis 应用的策略
redis 应用的过期键值删除策略是:惰性删除加上定期删除,两者配合应用。
数据淘汰策略
能够设置内存最大使用量,当内存使用量超出时,会实施数据淘汰策略。
Redis 具体有 6 种淘汰策略:
作为内存数据库,出于对性能和内存耗费的思考,Redis 的淘汰算法理论实现上并非针对所有 key,而是抽样一小部分并且从中选出被淘汰的 key。
Redis 4.0 引入了 volatile-lfu 和 allkeys-lfu 淘汰策略,LFU 策略通过统计拜访频率,将拜访频率起码的键值对淘汰。
您须要依据零碎的特色,来抉择适合的淘汰策略。当然,在运行过程中也能够通过命令动静设置淘汰策略,并通过 INFO 命令监控缓存的 miss 和 hit,来进行调优。
淘汰策略的外部实现
- 客户端执行一个命令,导致 Redis 中的数据减少,占用更多内存
- Redis 查看内存使用量,如果超出 maxmemory 限度,依据策略革除局部 key
- 继续执行下一条命令,以此类推
在这个过程中,内存使用量会一直地达到 limit 值,而后超过,而后删除局部 key,使用量又降落到 limit 值之下。
如果某个命令导致大量内存占用(比方通过新 key 保留一个很大的 set),在一段时间内,可能内存的使用量会显著超过 maxmemory 限度。
Redis 与 Memcached 的区别
两者都是非关系型内存键值数据库,当初公司个别都是用 Redis 来实现缓存,而且 Redis 本身也越来越弱小了!Redis 与 Memcached 的区别请参考:Redis 与 Memcached 的区别
事务
Redis 通过 MULTI、EXEC、WATCH 等命令来实现事务 (transaction) 性能。事务提供了一种将多个命令申请打包,而后一次性、按程序地执行多个命令的机制,并且在事务执行期间,服务器不会中断事务而改去执行其余客户端的命令申请,它会将事务中的所有命令都执行结束,而后才去解决其余客户端的命令申请。
事务中的多个命令被一次性发送给服务器,而不是一条一条发送,这种形式被称为流水线,能够缩小客户端与服务器之间的网络通信次数从而晋升性能。
在传统的关系式数据库中,罕用 ACID 性质来测验事务性能的可靠性和安全性。在 Redis 中,事务总是具备原子性(Atomicity)、一致性(Consistency)和隔离性(Isolation),并且当 Redis 运行在某种特定的长久化模式下时,事务也具备持久性(Durability)。
- 事件
Redis 服务器是一个事件驱动程序。
- 文件事件
服务器通过套接字与客户端或者其它服务器进行通信,文件事件就是对套接字操作的形象。
Redis 基于 Reactor 模式开发了本人的网络事件处理器,应用 I/O 多路复用程序来同时监听多个套接字,并将达到的事件传送给文件事件分派器,分派器会依据套接字产生的事件类型调用相应的事件处理器。
- 工夫事件
服务器有一些操作须要在给定的工夫点执行,工夫事件是对这类定时操作的形象。
工夫事件又分为:
- 定时事件:是让一段程序在指定的工夫之内执行一次
- 周期性事件:是让一段程序每隔指定工夫就执行一次
目前 Redis 只应用周期性事件,而没有应用定时事件。一个事件工夫次要由三个属性组成:
- id:服务器为工夫事件创立的全局惟一 ID
- when:毫秒精度的 UNIX 工夫戳,记录了工夫事件的达到工夫
- timeProc:工夫事件处理器,一个函数
实现服务器将所有工夫事件都放在一个无序链表中,每当工夫事件执行器运行时,遍历整个链表,查找所有已达到的工夫事件,并调用相应的事件处理器。(该链表为无序链表,不按 when 属性的大小排序)
- 事件的调度与执行
服务器须要一直监听文件事件的套接字能力失去待处理的文件事件,然而不能始终监听,否则工夫事件无奈在规定的工夫内执行,因而监听工夫应该依据间隔当初最近的工夫事件来决定。
Sentinel
Sentinel(哨兵)能够监听集群中的服务器,并在主服务器进入下线状态时,主动从从服务器中选举出新的主服务器。
Redis 集群生产环境高可用计划实战过程
分片
分片是将数据划分为多个局部的办法,能够将数据存储到多台机器外面,这种办法在解决某些问题时能够取得线性级别的性能晋升。
假如有 4 个 Redis 实例 R0,R1,R2,R3,还有很多示意用户的键 user:1,user:2,…,有不同的形式来抉择一个指定的键存储在哪个实例中。
最简略的形式是范畴分片,例如用户 id 从 0~1000 的存储到实例 R0 中,用户 id 从 1001~2000 的存储到实例 R1 中,等等。然而这样须要保护一张映射范畴表,保护操作代价很高。
还有一种形式是哈希分片,应用 CRC32 哈希函数将键转换为一个数字,再对实例数量求模就能晓得应该存储的实例。
依据执行分片的地位,能够分为三种分片形式:
- 客户端分片:客户端应用一致性哈希等算法决定键该当散布到哪个节点。
- 代理分片:将客户端申请发送到代理上,由代理转发申请到正确的节点上。
- 服务器分片:Redis Cluster。
复制
通过应用 slaveof host port 命令来让一个服务器成为另一个服务器的从服务器。
一个从服务器只能有一个主服务器,并且不反对主主复制。
-
连贯过程
- 主服务器创立快照文件,发送给从服务器,并在发送期间应用缓冲区记录执行的写命令。快照文件发送结束之后,开始向从服务器发送存储在缓冲区中的写命令
- 从服务器抛弃所有旧数据,载入主服务器发来的快照文件,之后从服务器开始承受主服务器发来的写命令
- 主服务器每执行一次写命令,就向从服务器发送雷同的写命令
- 主从链
随着负载一直回升,主服务器可能无奈很快地更新所有从服务器,或者从新连贯和从新同步从服务器将导致系统超载。为了解决这个问题,能够创立一个中间层来分担主服务器的复制工作。中间层的服务器是最上层服务器的从服务器,又是最上层服务器的主服务器。
Redis 中缓存雪崩、缓存穿透等问题的解决方案
缓存雪崩
缓存雪崩是指缓存同一时间大面积的生效,所以,前面的申请都会落到数据库上,造成数据库短时间内接受大量申请而崩掉。
解决方案
- 缓存数据的过期工夫设置随机,避免同一时间大量数据过期景象产生。
- 个别并发量不是特地多的时候,应用最多的解决方案是加锁排队。
- 给每一个缓存数据减少相应的缓存标记,记录缓存的是否生效,如果缓存标记生效,则更新数据缓存。
缓存穿透
缓存穿透是指缓存和数据库中都没有的数据,导致所有的申请都落到数据库上,造成数据库短时间内接受大量申请而崩掉。
解决方案
- 接口层减少校验,如用户鉴权校验,id 做根底校验,id<= 0 的间接拦挡;
- 从缓存取不到的数据,在数据库中也没有取到,这时也能够将 key-value 对写为 key-null,缓存无效工夫能够设置短点,如 30 秒(设置太长会导致失常状况也没法应用)。这样能够避免攻打用户重复用同一个 id 暴力攻打
- 采纳布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个肯定不存在的数据会被这个 bitmap 拦挡掉,从而防止了对底层存储系统的查问压力
附加
- 对于空间的利用达到了一种极致,那就是 Bitmap 和布隆过滤器(Bloom Filter)。
- Bitmap:典型的就是哈希表
- 毛病是,Bitmap 对于每个元素只能记录 1bit 信息,如果还想实现额定的性能,恐怕只能靠就义更多的空间、工夫来实现了。
布隆过滤器(举荐)
- 就是引入了 k(k>1)k(k>1)个互相独立的哈希函数,保障在给定的空间、误判率下,实现元素判重的过程。
- 它的长处是空间效率和查问工夫都远远超过个别的算法,毛病是有肯定的误识别率和删除艰难。
- Bloom-Filter 算法的核心思想就是利用多个不同的 Hash 函数来解决“抵触”。
- Hash 存在一个抵触(碰撞)的问题,用同一个 Hash 失去的两个 URL 的值有可能雷同。为了缩小抵触,咱们能够多引入几个 Hash,如果通过其中的一个 Hash 值咱们得出某元素不在汇合中,那么该元素必定不在汇合中。只有在所有的 Hash 函数通知咱们该元素在汇合中时,能力确定该元素存在于汇合中。这便是 Bloom-Filter 的根本思维。
- Bloom-Filter 个别用于在大数据量的汇合中断定某元素是否存在。
缓存击穿
缓存击穿是指缓存中没有但数据库中有的数据(个别是缓存工夫到期),这时因为并发用户特地多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力霎时增大,造成过大压力。和缓存雪崩不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
解决方案
- 设置热点数据永远不过期。
- 加互斥锁,互斥锁
缓存预热
缓存预热就是零碎上线后,将相干的缓存数据间接加载到缓存零碎。这样就能够防止在用户申请的时候,先查询数据库,而后再将数据缓存的问题!用户间接查问当时被预热的缓存数据!
解决方案
- 间接写个缓存刷新页面,上线时手工操作一下;
- 数据量不大,能够在我的项目启动的时候主动进行加载;
- 定时刷新缓存;
缓存降级
当访问量剧增、服务呈现问题(如响应工夫慢或不响应)或非核心服务影响到外围流程的性能时,依然须要保障服务还是可用的,即便是有损服务。零碎能够依据一些要害数据进行主动降级,也能够配置开关实现人工降级。
缓存降级的最终目标是保障外围服务可用,即便是有损的。而且有些服务是无奈降级的(如退出购物车、结算)。
在进行降级之前要对系统进行梳理,看看零碎是不是能够丢卒保帅;从而梳理出哪些必须誓死爱护,哪些可降级;比方能够参考日志级别设置预案:
个别:比方有些服务偶然因为网络抖动或者服务正在上线而超时,能够主动降级;
正告:有些服务在一段时间内成功率有稳定(如在 95~100% 之间),能够主动降级或人工降级,并发送告警;
谬误:比方可用率低于 90%,或者数据库连接池被打爆了,或者访问量忽然猛增到零碎能接受的最大阀值,此时能够依据状况主动降级或者人工降级;
严重错误:比方因为非凡起因数据谬误了,此时须要紧急人工降级。
服务降级的目标,是为了避免 Redis 服务故障,导致数据库跟着一起产生雪崩问题。因而,对于不重要的缓存数据,能够采取服务降级策略,例如一个比拟常见的做法就是,Redis 呈现问题,不去数据库查问,而是间接返回默认值给用户。
热点数据和冷数据
热点数据,缓存才有价值
对于冷数据而言,大部分数据可能还没有再次拜访到就曾经被挤出内存,不仅占用内存,而且价值不大。频繁批改的数据,看状况思考应用缓存
对于热点数据,比方咱们的某 IM 产品,生日祝愿模块,当天的寿星列表,缓存当前可能读取数十万次。再举个例子,某导航产品,咱们将导航信息,缓存当前可能读取数百万次。
数据更新前至多读取两次,缓存才有意义。这个是最根本的策略,如果缓存还没有起作用就生效了,那就没有太大价值了。
那存不存在,批改频率很高,然而又不得不思考缓存的场景呢?有!比方,这个读取接口对数据库的压力很大,然而又是热点数据,这个时候就须要思考通过缓存伎俩,缩小数据库的压力,比方咱们的某助手产品的,点赞数,珍藏数,分享数等是十分典型的热点数据,然而又一直变动,此时就须要将数据同步保留到 Redis 缓存,缩小数据库压力。
缓存热点 key
缓存中的一个 Key(比方一个促销商品),在某个工夫点过期的时候,恰好在这个工夫点对这个 Key 有大量的并发申请过去,这些申请发现缓存过期个别都会从后端 DB 加载数据并回设到缓存,这个时候大并发的申请可能会霎时把后端 DB 压垮。
解决方案
对缓存查问加锁,如果 KEY 不存在,就加锁,而后查 DB 入缓存,而后解锁;其余过程如果发现有锁就期待,而后等解锁后返回数据或者进入 DB 查问
以上内容参考链接:https://blog.csdn.net/ThinkWo…
Redis 优化最佳实际
咱们就来总结一下,在应用 Redis 时的最佳实际形式,次要蕴含两个层面:业务层面、运维层面。
因为我之前写过很多 UGC 后端服务,在大量场景下用到了 Redis,这个过程中也踩过很多坑,所以在应用过程中也总结了一套正当的应用办法。
起初做基础架构,开发 Codis、Redis 相干的中间件,在这个阶段关注畛域从应用层面下沉到 Redis 的开发和运维,更多聚焦在 Redis 的外部实现和运维过程中产生的各种问题,在这块也积攒了一些教训。
上面就针对这两块,分享一下我认为比拟正当的 Redis 应用和运维办法,不肯定最全面,也可能与你应用 Redis 的办法不同,但以下这些办法都是我在踩坑之后总结的理论教训,供你参考。关注公众号 Java 技术栈回复 redis 获取系列 Redis 教程。
业务层面次要是开发人员须要关注,也就是开发人员在写业务代码时,如何正当地应用 Redis。开发人员须要对 Redis 有根本的理解,能力在适合的业务场景应用 Redis,从而防止业务层面导致的提早问题。
在开发过程中,业务层面的优化倡议如下:
- key 的长度尽量要短,在数据量十分大时,过长的 key 名会占用更多的内存
- 肯定防止存储过大的数据(大 value),过大的数据在分配内存和开释内存时耗时重大,会阻塞主线程
- Redis 4.0 以上倡议开启 lazy-free 机制,开释大 value 时异步操作,不阻塞主线程
- 倡议设置过期工夫,把 Redis 当做缓存应用,尤其在数量很大的时,不设置过期工夫会导致内存的有限增长
- 不应用简单度过高的命令,例如 SORT、SINTER、SINTERSTORE、ZUNIONSTORE、ZINTERSTORE,应用这些命令耗时较久,会阻塞主线程
- 查问数据时,一次尽量获取较少的数据,在不确定容器元素个数的状况下,防止应用 LRANGE key 0 -1,ZRANGE key 0 - 1 这类操作,应该设置具体查问的元素个数,举荐一次查问 100 个以下元素
- 写入数据时,一次尽量写入较少的数据,例如 HSET key value1 value2 value3…,- 管制一次写入元素的数量,举荐在 100 以下,大数据量分多个批次写入
- 批量操作数据时,用 MGET/MSET 替换 GET/SET、HMGET/MHSET 替换 HGET/HSET,缩小申请来回的网络 IO 次数,升高提早,对于没有批量操作的命令,举荐应用 pipeline,一次性发送多个命令到服务端
- 禁止应用 KEYS 命令,须要扫描实例时,倡议应用 SCAN,线上操作肯定要管制扫描的频率,防止对 Redis 产生性能抖动
- 防止某个工夫点集中过期大量的 key,集中过期时举荐减少一个随机工夫,把过期工夫打散,升高集中过期 key 时 Redis 的压力,防止阻塞主线程
- 依据业务场景,抉择适合的淘汰策略,通常随机过期要比 LRU 过期淘汰数据更快
- 应用连接池拜访 Redis,并配置正当的连接池参数,防止短连贯,TCP 三次握手和四次挥手的耗时也很高
- 只应用 db0,不举荐应用多个 db,应用多个 db 会减少 Redis 的累赘,每次拜访不同的 db 都须要执行 SELECT 命令,如果业务线不同,倡议拆分多个实例,还能进步单个实例的性能
- 读的申请量很大时,举荐应用读写拆散,前提是能够容忍从节数据更新不及时的问题
-
写申请量很大时,举荐应用集群,部署多个实例摊派写压力
运维层面
目标是正当布局 Redis 的部署和保障 Redis 的稳固运行,次要优化如下:
- 不同业务线部署不同的实例,各自独立,防止混用,举荐不同业务线应用不同的机器,依据业务重要水平划分不同的分组来部署,防止某一个业务线呈现问题影响其余业务线
- 保障机器有足够的 CPU、内存、带宽、磁盘资源,避免负载过高影响 Redis 性能
- 以 master-slave 集群形式部署实例,并散布在不同机器上,防止单点,slave 必须设置为 readonly
- master 和 slave 节点所在机器,各自独立,不要穿插部署实例,通常备份工作会在 slave 上做,做备份时会耗费机器资源,穿插部署会影响到 master 的性能
- 举荐部署哨兵节点减少可用性,节点数量至多 3 个,并散布在不同机器上,实现故障主动故障转移
- 提前做好容量布局,一台机器部署实例的内存下限,最好是机器内存的一半,主从全量同步时会占用最多额定一倍的内存空间,防止网络大面积故障引发所有 master-slave 的全量同步导致机器内存被吃光
- 做好机器的 CPU、内存、带宽、磁盘监控,在资源有余时及时报警解决,Redis 应用 Swap 后性能急剧下降,网络带宽负载过高拜访提早显著增大,磁盘 IO 过高时开启 AOF 会拖慢 Redis 的性能
- 设置最大连接数下限,避免过多的客户端连贯导致服务负载过高
- 单个实例的应用内存倡议管制在 20G 以下,过大的实例会导致备份工夫久、资源耗费多,主从全量同步数据工夫阻塞工夫更长
- 设置正当的 slowlog 阈值,举荐 10 毫秒,并对其进行监控,产生过多的慢日志须要及时报警 设置正当的复制缓冲区 repl-backlog 大小,适当调大 repl-backlog 能够升高主从全量复制的概率
- 设置正当的 slave 节点 client-output-buffer-limit 大小,对于写入量很大的实例,适当调大能够防止主从复制中断问题
- 备份时举荐在 slave 节点上做,不影响 master 性能
- 不开启 AOF 或开启 AOF 配置为每秒刷盘,防止磁盘 IO 耗费升高 Redis 性能
- 当实例设置了内存下限,须要调大内存下限时,先调整 slave 再调整 master,否则会导致主从节点数据不统一
- 对 Redis 减少监控,监控采集 info 信息时,应用长连贯,频繁的短连贯也会影响 Redis 性能,redis 性能监控指标,参考这个文章
- 线上扫描整个实例数时,记得设置休眠工夫,防止扫描时 QPS 突增对 Redis 产生性能抖
- 做好 Redis 的运行时监控,尤其是 expired\_keys、evicted\_keys、latest\_fork\_usec 指标,短时间内这些指标值突增可能会阻塞整个实例,引发性能问题
以上就是我在应用 Redis 和开发 Redis 相干中间件时,总结进去 Redis 举荐的实际办法,以上提出的这些方面,都或多或少在理论应用中遇到过。
可见,要想稳固施展 Redis 的高性能,须要在各个方面做好工作,凡是某一个方面呈现问题,必然会影响到 Redis 的性能,这对咱们应用和运维提出了更高的要求。
如果你在应用 Redis 过程中,遇到更多的问题或者有更好的应用教训,能够留言一起探讨!
出处:kaito-kidd.com/2020/07/04/redis-best-practices/
Redis 其它总结
阿里云 Redis 开发标准学习总结
目前 Redis 可视化工具最全的横向评测
Redis 性能测试工具介绍
Redis 可视化管理工具
Redis 越来越慢?常见提早问题定位与剖析
Redis 分布式集群部署
原理:
- Redis 集群采纳一致性哈希槽的形式将集群中每个主节点都调配肯定的哈希槽,对写入的数据进行哈希后调配到某个主节点进行存储。
- 集群应用公式(CRC16 key)& 16384 计算键 key 数据那个槽。
- 16384 个 slot 均匀分布在各个节点上。
-
集群中每个主节点将承当一部分槽点的保护,而槽点中存储着数据,每个主节点都有至多一个从节点用于高可用。
节点通信形式:
- 开启一个端口 设置的端口号 +10000,用于集群之间节点通信替换信息。
- 每个节点默认每秒 10 次抉择随机 5 个节点发送 ping 音讯,将本身信息和晓得的集群信息传递,收到 ping 音讯后返回 pong 音讯做回复,最初通过这种随机的音讯替换,最终每个节点将取得所有信息。
- 当某个主节点挂掉,所有节点将会发现主节点挂掉了,作为主节点的从节点,就会接替主节点的工作,而后通知所有其它节点,他成为了主。这样其它存活节点,就将它们保护的信息表更新从节点将接任做主,如果都挂掉集群将报错。当从一个节点操作,依据一致性哈希计算后将存储在其中一个主节点中,从节点将同步主的数据。
-
redis cluster 是去中心化的,集群中的每个节点都是平等的关系,每个节点都保留各自的数据和整个集群的状态。每个节点都和其余所有节点连贯,而且这些连贯放弃沉闷。
-
搭建集群时,会为每一个分片的主节点,对应一个从节点。实现 slaveof 性能,同时当主节点 down,实现 sentinel 哨兵的主动 failover 切换性能
Redis 分布式集群(部署):
端口号:7000-7005
本次分布式分片集群在一台 LInux 零碎即可,只须要装置多个实例作为集群配置。
装置 ruby 环境反对:
yum -y install ruby rubygems
yum 装置 2.0.0 版本,然而 gem 须要 2.2.2 版本以上,所以抉择编译
下载并装置 ruby 环境:
wget https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.1.tar.gz
tar xf ruby-2.6.1.tar.gz && cd ruby-2.6.1/
./configure --prefix=/usr/local/ruby
make && make install && echo $?
echo 'export PATH=$PATH:/usr/local/ruby/bin' >> /etc/profile
source /etc/profile
批改 gem 工具国内源:
# 查看 gem 工具源地址
gem sources -l
# 增加一个阿里云的 gem 工具源
gem sources -a http://mirrors.aliyun.com/rubygems/
# 删除 gem 工具默认国外源
gem sources --remove https://rubygems.org/
# 下载以后最新版本集群插件
gem install redis -v 4.1.0
集群节点筹备:
mkdir /data/700{0..5}
配置 7000 端口实例:
vim /data/7000/redis.conf
port 7000
daemonize yes
pidfile /data/7000/redis.pid
loglevel notice
logfile "/data/7000/redis.log"
dbfilename dump.rdb
dir /data/7000
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
拷贝其余端口实例:
# 拷贝配置文件
cp /data/7000/redis.conf /data/7001/
cp /data/7000/redis.conf /data/7002/
cp /data/7000/redis.conf /data/7003/
cp /data/7000/redis.conf /data/7004/
cp /data/7000/redis.conf /data/7005/
# 批改配置文件内容
sed -i 's#7000#7001#g' /data/7001/redis.conf
sed -i 's#7000#7002#g' /data/7002/redis.conf
sed -i 's#7000#7003#g' /data/7003/redis.conf
sed -i 's#7000#7004#g' /data/7004/redis.conf
sed -i 's#7000#7005#g' /data/7005/redis.conf
启动所有实例:
redis-server /data/7000/redis.conf
redis-server /data/7001/redis.conf
redis-server /data/7002/redis.conf
redis-server /data/7003/redis.conf
redis-server /data/7004/redis.conf
redis-server /data/7005/redis.conf
创立命令软链接:
(这个命令过期了,当初应用 redis-cli 命令)(可选执行命令)
ln -s /usr/local/redis-5.0.2/src/redis-trib.rb /usr/sbin/
查看过程:
ps -ef |grep redis-server
退出所有实例节点到集群治理:
# --replicas 1",1 是代表每一个主有一个从, 前面的是所有节点的地址与端口信息
redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
分布式主从规定为,前三个实例节点是主,对应的前面三个实例节点为从节点,如果 replicas 2,那就多加 3 个实例节点
查看主节点状态:
redis-cli -p 7000 cluster nodes|grep master
查看从节点状态:
redis-cli -p 7000 cluster nodes|grep slave
Redis- 分布式集群(治理)
集群节点减少筹备:
mkdir /data/700{6..7}
拷贝其余端口实例:# 拷贝配置文件
cp /data/7000/redis.conf /data/7006/
cp /data/7000/redis.conf /data/7007/
# 批改配置文件内容
sed -i 's#7000#7006#g' /data/7006/redis.conf
sed -i 's#7000#7007#g' /data/7007/redis.conf
启动新节点实例:
redis-server /data/7006/redis.conf
redis-server /data/7007/redis.conf
查看过程:
ps -ef |grep redis-server
增加主节点:(7000 实例是治理节点)
#' 把 7006 实例增加到 7000 实例这个主节点所在集群内(此时曾经有了 4 个主节点)
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
查看主节点状态:
redis-cli -p 7000 cluster nodes|grep master
转移 slot(从新分片):
#' 操作集群治理节点从新调配,并在交互界面指定分片大小、抉择接管分片的节点 ID
redis-cli --cluster reshard 127.0.0.1:7000
How many slots do you want to move (from 1 to 16384)? 4096
#通过人工手动计算数据分片总大小除以主节点后的数字
What is the receiving node ID? 2129d28f0a86fc89571e49a59a0739812cff7953
#抉择接收数据分片的节点 ID,(这是新增节点 7006 实例的 ID 号)Source node #1: all
#抉择从哪些源主节点从新分片给新主节点)(all 是所有节点)Do you want to proceed with the proposed reshard plan (yes/no)? yes
#确认批改以上的操作
从新查看主节点状态:(能够看到集群数据的从新分片)
redis-cli -p 7000 cluster nodes|grep master
增加从节点:
#' 把 7007 实例节点增加到 7006 实例主节点内,并指定对应 7006 实例主节点坐在集群的治理节点
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7000 --cluster-slave --cluster-master-id 2129d28f0a86fc89571e49a59a0739812cff7953
查看从节点状态:
redis-cli -p 7000 cluster nodes|grep slave
集群节点删除筹备:
挪动要删除节点的数据分片:
#' 操作集群治理节点从新调配,并在交互界面指定分片大小、抉择接管分片的节点 ID
redis-cli --cluster reshard 127.0.0.1:7000
#办法是依据要删除 master 节点的分片地位,而后一个组分一个节点,也能够间接挪动所有数据片到一个节点
How many slots do you want to move (from 1 to 16384)? 1365
#通过人工手动查看数据分片总大小
What is the receiving node ID? e64f9074a3733fff7baa9a4848190e56831d5447
#抉择接收数据分片的节点 ID,(这是新增节点 7006 实例的 ID 号)Source node #1: 2129d28f0a86fc89571e49a59a0739812cff7953
#抉择从哪些源主节点从新分片给新主节点(这是要删除的主节点的 ID 号)Source node #2: done
#这是完结命令
Do you want to proceed with the proposed reshard plan (yes/no)? yes
#确认批改以上的操作
从新查看主节点状态:(能够看到集群数据的从新分片)
redis-cli -p 7000 cluster nodes|grep master
继续移动数据片:
#' 操作集群治理节点从新调配,并在交互界面指定分片大小、抉择接管分片的节点 ID
redis-cli --cluster reshard 127.0.0.1:7000
# 办法是依据要删除 master 节点的分片地位,而后一个组分一个节点,也能够间接挪动所有数据片到一个节点
How many slots do you want to move (from 1 to 16384)? 1366 #通过人工手动查看数据分片总大小
What is the receiving node ID? f6c1aaea3a8c56e0c7dee8ad7ae17e26dd04244c
#抉择接收数据分片的节点 ID,(这是新增节点 7006 实例的 ID 号)Source node #1: 2129d28f0a86fc89571e49a59a0739812cff7953
#抉择从哪些源主节点从新分片给新主节点(这是要删除的主节点的 ID 号)Source node #2: done
#这是完结命令
Do you want to proceed with the proposed reshard plan (yes/no)? yes
#确认批改以上的操作
从新查看主节点状态:(能够看到集群数据的从新分片)
redis-cli -p 7000 cluster nodes|grep master
最初一次挪动数据片:
#' 操作集群治理节点从新调配,并在交互界面指定分片大小、抉择接管分片的节点 ID
redis-cli --cluster reshard 127.0.0.1:7000
#办法是依据要删除 master 节点的分片地位,而后一个组分一个节点,也能够间接挪动所有数据片到一个节点
How many slots do you want to move (from 1 to 16384)? 1365
#通过人工手动查看数据分片总大小
What is the receiving node ID? 5a0df4ea0af5f35c1248e45e88d44c3f2e10169f
Source node #1: 2129d28f0a86fc89571e49a59a0739812cff7953
Source node #2: done
从新查看主节点状态:(能够看到集群数据的从新分片)
redis-cli -p 7000 cluster nodes|grep master
删除清空数据片的主节点:
#' 删除曾经清空数据的 7006 实例
redis-cli --cluster del-node 127.0.0.1:7006 2129d28f0a86fc89571e49a59a0739812cff7953
#删除没有主库的 7007 实例
redis-cli --cluster del-node 127.0.0.1:7007 821bcf78c5e4c0b08aa7a5d514214b657ebec4ab
其余配置管理:
# 内存信息查看
redis-cli -p 6382 -a redhat info memory
#设置最大只能应用 100MB 的内存
redis-cli -p 6382 -a redhat config set maxmemory 102400000
史上最全、最新的 Redis 面试题(最新版)