当前位置: 首页 > news >正文

正规企业网站开发使用方法ps做图 游戏下载网站

正规企业网站开发使用方法,ps做图 游戏下载网站,搭建网站的免费程序,市场营销策划案Redis 作为优秀的内存数据库#xff0c;其拥有非常高的性能#xff0c;单个实例的 OPS 能够达到 10W 左右。但也正因此如此#xff0c;当我们在使用 Redis 时#xff0c;如果发现操作延迟变大的情况#xff0c;就会与我们的预期不符。你也许或多或少地#xff0c;也遇到过… Redis 作为优秀的内存数据库其拥有非常高的性能单个实例的 OPS 能够达到 10W 左右。但也正因此如此当我们在使用 Redis 时如果发现操作延迟变大的情况就会与我们的预期不符。你也许或多或少地也遇到过以下这些场景在 Redis 上执行同样的命令为什么有时响应很快有时却很慢为什么 Redis 执行 SET、DEL 命令耗时也很久为什么我的 Redis 突然慢了一波之后又恢复正常了为什么我的 Redis 稳定运行了很久突然从某个时间点开始变慢了...如果你并不清楚 Redis 内部的实现原理那么在排查这种延迟问题时就会一头雾水。如果你也遇到了以上情况那么这篇文章将会给你一个「全面」的问题排查思路并且针对这些导致变慢的场景我还会给你一个高效的解决方案。在正文开始之前我需要提醒你的是这篇文章很长涵盖的 Redis 知识点也非常广全篇文章接近 2W 字如果此时你的阅读环境不适合专注阅读我建议你先收藏此文章然后在合适的时间专注阅读这篇文章。如果你能耐心且认真地读完这篇文章我可以保证你对 Redis 的性能调优将会有非常大的收获。如果你准备好了那就跟着我的思路开始吧Redis真的变慢了吗首先在开始之前你需要弄清楚 Redis 是否真的变慢了如果你发现你的业务服务 API 响应延迟变长首先你需要先排查服务内部究竟是哪个环节拖慢了整个服务。比较高效的做法是在服务内部集成链路追踪也就是在服务访问外部依赖的出入口记录下每次请求外部依赖的响应延时。如果你发现确实是操作 Redis 的这条链路耗时变长了那么此刻你需要把焦点关注在业务服务到 Redis 这条链路上。从你的业务服务到 Redis 这条链路变慢的原因可能也有 2 个业务服务器到 Redis 服务器之间的网络存在问题例如网络线路质量不佳网络数据包在传输时存在延迟、丢包等情况Redis 本身存在问题需要进一步排查是什么原因导致 Redis 变慢通常来说第一种情况发生的概率比较小如果是服务器之间网络存在问题那部署在这台业务服务器上的所有服务都会发生网络延迟的情况此时你需要联系网络运维同事让其协助解决网络问题。我们这篇文章重点关注的是第二种情况。也就是从 Redis 角度来排查是否存在导致变慢的场景以及都有哪些因素会导致 Redis 的延迟增加然后针对性地进行优化。排除网络原因如何确认你的 Redis 是否真的变慢了首先你需要对 Redis 进行基准性能测试了解你的 Redis 在生产环境服务器上的基准性能。什么是基准性能简单来讲基准性能就是指 Redis 在一台负载正常的机器上其最大的响应延迟和平均响应延迟分别是怎样的为什么要测试基准性能我参考别人提供的响应延迟判断自己的 Redis 是否变慢不行吗答案是否定的。因为 Redis 在不同的软硬件环境下它的性能是各不相同的。例如我的机器配置比较低当延迟为 2ms 时我就认为 Redis 变慢了但是如果你的硬件配置比较高那么在你的运行环境下可能延迟是 0.5ms 时就可以认为 Redis 变慢了。所以你只有了解了你的 Redis 在生产环境服务器上的基准性能才能进一步评估当其延迟达到什么程度时才认为 Redis 确实变慢了。具体如何做为了避免业务服务器到 Redis 服务器之间的网络延迟你需要直接在 Redis 服务器上测试实例的响应延迟情况。执行以下命令就可以测试出这个实例 60 秒内的最大响应延迟$ redis-cli -h 127.0.0.1 -p 6379 --intrinsic-latency 60 Max latency so far: 1 microseconds. Max latency so far: 15 microseconds. Max latency so far: 17 microseconds. Max latency so far: 18 microseconds. Max latency so far: 31 microseconds. Max latency so far: 32 microseconds. Max latency so far: 59 microseconds. Max latency so far: 72 microseconds.1428669267 total runs (avg latency: 0.0420 microseconds / 42.00 nanoseconds per run). Worst run took 1429x longer than the average latency. 从输出结果可以看到这 60 秒内的最大响应延迟为 72 微秒0.072毫秒。你还可以使用以下命令查看一段时间内 Redis 的最小、最大、平均访问延迟$ redis-cli -h 127.0.0.1 -p 6379 --latency-history -i 1 min: 0, max: 1, avg: 0.13 (100 samples) -- 1.01 seconds range min: 0, max: 1, avg: 0.12 (99 samples) -- 1.01 seconds range min: 0, max: 1, avg: 0.13 (99 samples) -- 1.01 seconds range min: 0, max: 1, avg: 0.10 (99 samples) -- 1.01 seconds range min: 0, max: 1, avg: 0.13 (98 samples) -- 1.00 seconds range min: 0, max: 1, avg: 0.08 (99 samples) -- 1.01 seconds range ... 以上输出结果是每间隔 1 秒采样 Redis 的平均操作耗时其结果分布在 0.08 ~ 0.13 毫秒之间。了解了基准性能测试方法那么你就可以按照以下几步来判断你的 Redis 是否真的变慢了在相同配置的服务器上测试一个正常 Redis 实例的基准性能找到你认为可能变慢的 Redis 实例测试这个实例的基准性能如果你观察到这个实例的运行延迟是正常 Redis 基准性能的 2 倍以上即可认为这个 Redis 实例确实变慢了确认是 Redis 变慢了那如何排查是哪里发生了问题呢下面跟着我的思路我们从易到难一步步来分析可能导致 Redis 变慢的因素。使用复杂度过高的命令首先第一步你需要去查看一下 Redis 的慢日志slowlog。Redis 提供了慢日志命令的统计功能它记录了有哪些命令在执行时耗时比较久。查看 Redis 慢日志之前你需要设置慢日志的阈值。例如设置慢日志的阈值为 5 毫秒并且保留最近 500 条慢日志记录# 命令执行耗时超过 5 毫秒记录慢日志 CONFIG SET slowlog-log-slower-than 5000 # 只保留最近 500 条慢日志 CONFIG SET slowlog-max-len 500 设置完成之后所有执行的命令如果操作耗时超过了 5 毫秒都会被 Redis 记录下来。此时你可以执行以下命令就可以查询到最近记录的慢日志127.0.0.1:6379 SLOWLOG get 5 1) 1) (integer) 32693       # 慢日志ID2) (integer) 1593763337  # 执行时间戳3) (integer) 5299        # 执行耗时(微秒)4) 1) LRANGE           # 具体执行的命令和参数2) user_list:20003) 04) -1 2) 1) (integer) 326922) (integer) 15937633373) (integer) 50444) 1) GET2) user_info:1000 ... 通过查看慢日志我们就可以知道在什么时间点执行了哪些命令比较耗时。如果你的应用程序执行的 Redis 命令有以下特点那么有可能会导致操作延迟变大经常使用 O(N) 以上复杂度的命令例如 SORT、SUNION、ZUNIONSTORE 聚合类命令使用 O(N) 复杂度的命令但 N 的值非常大第一种情况导致变慢的原因在于Redis 在操作内存数据时时间复杂度过高要花费更多的 CPU 资源。第二种情况导致变慢的原因在于Redis 一次需要返回给客户端的数据过多更多时间花费在数据协议的组装和网络传输过程中。另外我们还可以从资源使用率层面来分析如果你的应用程序操作 Redis 的 OPS 不是很大但 Redis 实例的 CPU 使用率却很高那么很有可能是使用了复杂度过高的命令导致的。除此之外我们都知道Redis 是单线程处理客户端请求的如果你经常使用以上命令那么当 Redis 处理客户端请求时一旦前面某个命令发生耗时就会导致后面的请求发生排队对于客户端来说响应延迟也会变长。针对这种情况如何解决呢答案很简单你可以使用以下方法优化你的业务尽量不使用 O(N) 以上复杂度过高的命令对于数据的聚合操作放在客户端做执行 O(N) 命令保证 N 尽量的小推荐 N 300每次获取尽量少的数据让 Redis 可以及时处理返回操作bigkey如果你查询慢日志发现并不是复杂度过高的命令导致的而都是 SET / DEL 这种简单命令出现在慢日志中那么你就要怀疑你的实例否写入了 bigkey。Redis 在写入数据时需要为新的数据分配内存相对应的当从 Redis 中删除数据时它会释放对应的内存空间。如果一个 key 写入的 value 非常大那么 Redis 在分配内存时就会比较耗时。同样的当删除这个 key 时释放内存也会比较耗时这种类型的 key 我们一般称之为 bigkey。此时你需要检查你的业务代码是否存在写入 bigkey 的情况。你需要评估写入一个 key 的数据大小尽量避免一个 key 存入过大的数据。如果已经写入了 bigkey那有没有什么办法可以扫描出实例中 bigkey 的分布情况呢答案是可以的。Redis 提供了扫描 bigkey 的命令执行以下命令就可以扫描出一个实例中 bigkey 的分布情况输出结果是以类型维度展示的$ redis-cli -h 127.0.0.1 -p 6379 --bigkeys -i 0.01... -------- summary -------Sampled 829675 keys in the keyspace! Total key length in bytes is 10059825 (avg len 12.13)Biggest string found key:291880 has 10 bytes Biggest   list found mylist:004 has 40 items Biggest    set found myset:2386 has 38 members Biggest   hash found myhash:3574 has 37 fields Biggest   zset found myzset:2704 has 42 members36313 strings with 363130 bytes (04.38% of keys, avg size 10.00) 787393 lists with 896540 items (94.90% of keys, avg size 1.14) 1994 sets with 40052 members (00.24% of keys, avg size 20.09) 1990 hashs with 39632 fields (00.24% of keys, avg size 19.92) 1985 zsets with 39750 members (00.24% of keys, avg size 20.03) 从输出结果我们可以很清晰地看到每种数据类型所占用的最大内存 / 拥有最多元素的 key 是哪一个以及每种数据类型在整个实例中的占比和平均大小 / 元素数量。其实使用这个命令的原理就是 Redis 在内部执行了 SCAN 命令遍历整个实例中所有的 key然后针对 key 的类型分别执行 STRLEN、LLEN、HLEN、SCARD、ZCARD 命令来获取 String 类型的长度、容器类型List、Hash、Set、ZSet的元素个数。这里我需要提醒你的是当执行这个命令时要注意 2 个问题对线上实例进行 bigkey 扫描时Redis 的 OPS 会突增为了降低扫描过程中对 Redis 的影响最好控制一下扫描的频率指定 -i 参数即可它表示扫描过程中每次扫描后休息的时间间隔单位是秒扫描结果中对于容器类型List、Hash、Set、ZSet的 key只能扫描出元素最多的 key。但一个 key 的元素多不一定表示占用内存也多你还需要根据业务情况进一步评估内存占用情况那针对 bigkey 导致延迟的问题有什么好的解决方案呢这里有两点可以优化业务应用尽量避免写入 bigkey如果你使用的 Redis 是 4.0 以上版本用 UNLINK 命令替代 DEL此命令可以把释放 key 内存的操作放到后台线程中去执行从而降低对 Redis 的影响如果你使用的 Redis 是 6.0 以上版本可以开启 lazy-free 机制lazyfree-lazy-user-del yes在执行 DEL 命令时释放内存也会放到后台线程中执行但即便可以使用方案 2我也不建议你在实例中存入 bigkey。这是因为 bigkey 在很多场景下依旧会产生性能问题。例如bigkey 在分片集群模式下对于数据的迁移也会有性能影响以及我后面即将讲到的数据过期、数据淘汰、透明大页都会受到 bigkey 的影响。集中过期如果你发现平时在操作 Redis 时并没有延迟很大的情况发生但在某个时间点突然出现一波延时其现象表现为变慢的时间点很有规律例如某个整点或者每间隔多久就会发生一波延迟。如果是出现这种情况那么你需要排查一下业务代码中是否存在设置大量 key 集中过期的情况。如果有大量的 key 在某个固定时间点集中过期在这个时间点访问 Redis 时就有可能导致延时变大。为什么集中过期会导致 Redis 延迟变大这就需要我们了解 Redis 的过期策略是怎样的。Redis 的过期数据采用被动过期 主动过期两种策略被动过期只有当访问某个 key 时才判断这个 key 是否已过期如果已过期则从实例中删除主动过期Redis 内部维护了一个定时任务默认每隔 100 毫秒1秒10次就会从全局的过期哈希表中随机取出 20 个 key然后删除其中过期的 key如果过期 key 的比例超过了 25%则继续重复此过程直到过期 key 的比例下降到 25% 以下或者这次任务的执行耗时超过了 25 毫秒才会退出循环注意这个主动过期 key 的定时任务是在 Redis 主线程中执行的。也就是说如果在执行主动过期的过程中出现了需要大量删除过期 key 的情况那么此时应用程序在访问 Redis 时必须要等待这个过期任务执行结束Redis 才可以服务这个客户端请求。此时就会出现应用访问 Redis 延时变大。如果此时需要过期删除的是一个 bigkey那么这个耗时会更久。而且这个操作延迟的命令并不会记录在慢日志中。因为慢日志中只记录一个命令真正操作内存数据的耗时而 Redis 主动删除过期 key 的逻辑是在命令真正执行之前执行的。所以此时你会看到慢日志中没有操作耗时的命令但我们的应用程序却感知到了延迟变大其实时间都花费在了删除过期 key 上这种情况我们需要尤为注意。那遇到这种情况如何分析和排查此时你需要检查你的业务代码是否存在集中过期 key 的逻辑。一般集中过期使用的是 expireat / pexpireat 命令你需要在代码中搜索这个关键字。排查代码后如果确实存在集中过期 key 的逻辑存在但这种逻辑又是业务所必须的那此时如何优化同时又不对 Redis 有性能影响呢一般有两种方案来规避这个问题集中过期 key 增加一个随机过期时间把集中过期的时间打散降低 Redis 清理过期 key 的压力如果你使用的 Redis 是 4.0 以上版本可以开启 lazy-free 机制当删除过期 key 时把释放内存的操作放到后台线程中执行避免阻塞主线程第一种方案在设置 key 的过期时间时增加一个随机时间伪代码可以这么写# 在过期时间点之后的 5 分钟内随机过期掉 redis.expireat(key, expire_time  random(300)) 这样一来Redis 在处理过期时不会因为集中删除过多的 key 导致压力过大从而避免阻塞主线程。第二种方案Redis 4.0 以上版本开启 lazy-free 机制# 释放过期 key 的内存放到后台线程执行 lazyfree-lazy-expire yes 另外除了业务层面的优化和修改配置之外你还可以通过运维手段及时发现这种情况。运维层面你需要把 Redis 的各项运行状态数据监控起来在 Redis 上执行 INFO 命令就可以拿到这个实例所有的运行状态数据。在这里我们需要重点关注 expired_keys 这一项它代表整个实例到目前为止累计删除过期 key 的数量。你需要把这个指标监控起来当这个指标在很短时间内出现了突增需要及时报警出来然后与业务应用报慢的时间点进行对比分析确认时间是否一致如果一致则可以确认确实是因为集中过期 key 导致的延迟变大。实例内存达到上限如果你的 Redis 实例设置了内存上限 maxmemory那么也有可能导致 Redis 变慢。当我们把 Redis 当做纯缓存使用时通常会给这个实例设置一个内存上限 maxmemory然后设置一个数据淘汰策略。而当实例的内存达到了 maxmemory 后你可能会发现在此之后每次写入新数据操作延迟变大了。这是为什么原因在于当 Redis 内存达到 maxmemory 后每次写入新的数据之前Redis 必须先从实例中踢出一部分数据让整个实例的内存维持在 maxmemory 之下然后才能把新数据写进来。这个踢出旧数据的逻辑也是需要消耗时间的而具体耗时的长短要取决于你配置的淘汰策略allkeys-lru不管 key 是否设置了过期淘汰最近最少访问的 keyvolatile-lru只淘汰最近最少访问、并设置了过期时间的 keyallkeys-random不管 key 是否设置了过期随机淘汰 keyvolatile-random只随机淘汰设置了过期时间的 keyallkeys-ttl不管 key 是否设置了过期淘汰即将过期的 keynoeviction不淘汰任何 key实例内存达到 maxmeory 后再写入新数据直接返回错误allkeys-lfu不管 key 是否设置了过期淘汰访问频率最低的 key4.0版本支持volatile-lfu只淘汰访问频率最低、并设置了过期时间 key4.0版本支持具体使用哪种策略我们需要根据具体的业务场景来配置。一般最常使用的是 allkeys-lru / volatile-lru 淘汰策略它们的处理逻辑是每次从实例中随机取出一批 key这个数量可配置然后淘汰一个最少访问的 key之后把剩下的 key 暂存到一个池子中继续随机取一批 key并与之前池子中的 key 比较再淘汰一个最少访问的 key。以此往复直到实例内存降到 maxmemory 之下。需要注意的是Redis 的淘汰数据的逻辑与删除过期 key 的一样也是在命令真正执行之前执行的也就是说它也会增加我们操作 Redis 的延迟而且写 OPS 越高延迟也会越明显。另外如果此时你的 Redis 实例中还存储了 bigkey那么在淘汰删除 bigkey 释放内存时也会耗时比较久。看到了么bigkey 的危害到处都是这也是前面我提醒你尽量不存储 bigkey 的原因。针对这种情况如何解决呢我给你 4 个方面的优化建议避免存储 bigkey降低释放内存的耗时淘汰策略改为随机淘汰随机淘汰比 LRU 要快很多视业务情况调整拆分实例把淘汰 key 的压力分摊到多个实例上如果使用的是 Redis 4.0 以上版本开启 layz-free 机制把淘汰 key 释放内存的操作放到后台线程中执行配置 lazyfree-lazy-eviction yesfork耗时严重为了保证 Redis 数据的安全性我们可能会开启后台定时 RDB 和 AOF rewrite 功能。但如果你发现操作 Redis 延迟变大都发生在 Redis 后台 RDB 和 AOF rewrite 期间那你就需要排查在这期间有可能导致变慢的情况。当 Redis 开启了后台 RDB 和 AOF rewrite 后在执行时它们都需要主进程创建出一个子进程进行数据的持久化。主进程创建子进程会调用操作系统提供的 fork 函数。而 fork 在执行过程中主进程需要拷贝自己的内存页表给子进程如果这个实例很大那么这个拷贝的过程也会比较耗时。而且这个 fork 过程会消耗大量的 CPU 资源在完成 fork 之前整个 Redis 实例会被阻塞住无法处理任何客户端请求。如果此时你的 CPU 资源本来就很紧张那么 fork 的耗时会更长甚至达到秒级这会严重影响 Redis 的性能。那如何确认确实是因为 fork 耗时导致的 Redis 延迟变大呢你可以在 Redis 上执行 INFO 命令查看 latest_fork_usec 项单位微秒。# 上一次 fork 耗时单位微秒 latest_fork_usec:59477 这个时间就是主进程在 fork 子进程期间整个实例阻塞无法处理客户端请求的时间。如果你发现这个耗时很久就要警惕起来了这意味在这期间你的整个 Redis 实例都处于不可用的状态。除了数据持久化会生成 RDB 之外当主从节点第一次建立数据同步时主节点也创建子进程生成 RDB然后发给从节点进行一次全量同步所以这个过程也会对 Redis 产生性能影响。要想避免这种情况你可以采取以下方案进行优化控制 Redis 实例的内存尽量在 10G 以下执行 fork 的耗时与实例大小有关实例越大耗时越久合理配置数据持久化策略在 slave 节点执行 RDB 备份推荐在低峰期执行而对于丢失数据不敏感的业务例如把 Redis 当做纯缓存使用可以关闭 AOF 和 AOF rewriteRedis 实例不要部署在虚拟机上fork 的耗时也与系统也有关虚拟机比物理机耗时更久降低主从库全量同步的概率适当调大 repl-backlog-size 参数避免主从全量同步开启内存大页除了上面讲到的子进程 RDB 和 AOF rewrite 期间fork 耗时导致的延时变大之外这里还有一个方面也会导致性能问题这就是操作系统是否开启了内存大页机制。什么是内存大页我们都知道应用程序向操作系统申请内存时是按内存页进行申请的而常规的内存页大小是 4KB。Linux 内核从 2.6.38 开始支持了内存大页机制该机制允许应用程序以 2MB 大小为单位向操作系统申请内存。应用程序每次向操作系统申请的内存单位变大了但这也意味着申请内存的耗时变长。这对 Redis 会有什么影响呢当 Redis 在执行后台 RDB 和 AOF rewrite 时采用 fork 子进程的方式来处理。但主进程 fork 子进程后此时的主进程依旧是可以接收写请求的而进来的写请求会采用 Copy On Write写时复制的方式操作内存数据。也就是说主进程一旦有数据需要修改Redis 并不会直接修改现有内存中的数据而是先将这块内存数据拷贝出来再修改这块新内存的数据这就是所谓的「写时复制」。写时复制你也可以理解成谁需要发生写操作谁就需要先拷贝再修改。这样做的好处是父进程有任何写操作并不会影响子进程的数据持久化子进程只持久化 fork 这一瞬间整个实例中的所有数据即可不关心新的数据变更因为子进程只需要一份内存快照然后持久化到磁盘上。但是请注意主进程在拷贝内存数据时这个阶段就涉及到新内存的申请如果此时操作系统开启了内存大页那么在此期间客户端即便只修改 10B 的数据Redis 在申请内存时也会以 2MB 为单位向操作系统申请申请内存的耗时变长进而导致每个写请求的延迟增加影响到 Redis 性能。同样地如果这个写请求操作的是一个 bigkey那主进程在拷贝这个 bigkey 内存块时一次申请的内存会更大时间也会更久。可见bigkey 在这里又一次影响到了性能。那如何解决这个问题很简单你只需要关闭内存大页机制就可以了。首先你需要查看 Redis 机器是否开启了内存大页$ cat /sys/kernel/mm/transparent_hugepage/enabled [always] madvise never 如果输出选项是 always就表示目前开启了内存大页机制我们需要关掉它$ echo never  /sys/kernel/mm/transparent_hugepage/enabled 其实操作系统提供的内存大页机制其优势是可以在一定程序上降低应用程序申请内存的次数。但是对于 Redis 这种对性能和延迟极其敏感的数据库来说我们希望 Redis 在每次申请内存时耗时尽量短所以我不建议你在 Redis 机器上开启这个机制。开启AOF前面我们分析了 RDB 和 AOF rewrite 对 Redis 性能的影响主要关注点在 fork 上。其实关于数据持久化方面还有影响 Redis 性能的因素这次我们重点来看 AOF 数据持久化。如果你的 AOF 配置不合理还是有可能会导致性能问题。当 Redis 开启 AOF 后其工作原理如下Redis 执行写命令后把这个命令写入到 AOF 文件内存中write 系统调用Redis 根据配置的 AOF 刷盘策略把 AOF 内存数据刷到磁盘上fsync 系统调用为了保证 AOF 文件数据的安全性Redis 提供了 3 种刷盘机制appendfsync always主线程每次执行写操作后立即刷盘此方案会占用比较大的磁盘 IO 资源但数据安全性最高appendfsync no主线程每次写操作只写内存就返回内存数据什么时候刷到磁盘交由操作系统决定此方案对性能影响最小但数据安全性也最低Redis 宕机时丢失的数据取决于操作系统刷盘时机appendfsync everysec主线程每次写操作只写内存就返回然后由后台线程每隔 1 秒执行一次刷盘操作触发fsync系统调用此方案对性能影响相对较小但当 Redis 宕机时会丢失 1 秒的数据下面我们依次来分析这几个机制对性能的影响。如果你的 AOF 配置为 appendfsync always那么 Redis 每处理一次写操作都会把这个命令写入到磁盘中才返回整个过程都是在主线程执行的这个过程必然会加重 Redis 写负担。原因也很简单操作磁盘要比操作内存慢几百倍采用这个配置会严重拖慢 Redis 的性能因此我不建议你把 AOF 刷盘方式配置为 always。我们接着来看 appendfsync no 配置项。在这种配置下Redis 每次写操作只写内存什么时候把内存中的数据刷到磁盘交给操作系统决定此方案对 Redis 的性能影响最小但当 Redis 宕机时会丢失一部分数据为了数据的安全性一般我们也不采取这种配置。如果你的 Redis 只用作纯缓存对于数据丢失不敏感采用配置 appendfsync no 也是可以的。看到这里我猜你肯定和大多数人的想法一样选比较折中的方案 appendfsync everysec 就没问题了吧这个方案优势在于Redis 主线程写完内存后就返回具体的刷盘操作是放到后台线程中执行的后台线程每隔 1 秒把内存中的数据刷到磁盘中。这种方案既兼顾了性能又尽可能地保证了数据安全是不是觉得很完美但是这里我要给你泼一盆冷水了采用这种方案你也要警惕一下因为这种方案还是存在导致 Redis 延迟变大的情况发生甚至会阻塞整个 Redis。这是为什么我把 AOF 最耗时的刷盘操作放到后台线程中也会影响到 Redis 主线程你试想这样一种情况当 Redis 后台线程在执行 AOF 文件刷盘时如果此时磁盘的 IO 负载很高那这个后台线程在执行刷盘操作fsync系统调用时就会被阻塞住。此时的主线程依旧会接收写请求紧接着主线程又需要把数据写到文件内存中write 系统调用但此时的后台子线程由于磁盘负载过高导致 fsync 发生阻塞迟迟不能返回那主线程在执行 write 系统调用时也会被阻塞住直到后台线程 fsync 执行完成后主线程执行 write 才能成功返回。看到了么在这个过程中主线程依旧有阻塞的风险。所以尽管你的 AOF 配置为 appendfsync everysec也不能掉以轻心要警惕磁盘压力过大导致的 Redis 有性能问题。那什么情况下会导致磁盘 IO 负载过大以及如何解决这个问题呢我总结了以下几种情况你可以参考进行问题排查子进程正在执行 AOF rewrite这个过程会占用大量的磁盘 IO 资源有其他应用程序在执行大量的写文件操作也会占用磁盘 IO 资源对于情况1说白了就是Redis 的 AOF 后台子线程刷盘操作撞上了子进程 AOF rewrite这怎么办难道要关闭 AOF rewrite 才行幸运的是Redis 提供了一个配置项当子进程在 AOF rewrite 期间可以让后台子线程不执行刷盘不触发 fsync 系统调用操作。这相当于在 AOF rewrite 期间临时把 appendfsync 设置为了 none配置如下# AOF rewrite 期间AOF 后台子线程不进行刷盘操作 # 相当于在这期间临时把 appendfsync 设置为了 none no-appendfsync-on-rewrite yes 当然开启这个配置项在 AOF rewrite 期间如果实例发生宕机那么此时会丢失更多的数据性能和数据安全性你需要权衡后进行选择。如果占用磁盘资源的是其他应用程序那就比较简单了你需要定位到是哪个应用程序在大量写磁盘然后把这个应用程序迁移到其他机器上执行就好了避免对 Redis 产生影响。当然如果你对 Redis 的性能和数据安全都有很高的要求那么我建议从硬件层面来优化更换为 SSD 磁盘提高磁盘的 IO 能力保证 AOF 期间有充足的磁盘资源可以使用。绑定CPU很多时候我们在部署服务时为了提高服务性能降低应用程序在多个 CPU 核心之间的上下文切换带来的性能损耗通常采用的方案是进程绑定 CPU 的方式提高性能。但在部署 Redis 时如果你需要绑定 CPU 来提高其性能我建议你仔细斟酌后再做操作。为什么因为 Redis 在绑定 CPU 时是有很多考究的如果你不了解 Redis 的运行原理随意绑定 CPU 不仅不会提高性能甚至有可能会带来相反的效果。我们都知道一般现代的服务器会有多个 CPU而每个 CPU 又包含多个物理核心每个物理核心又分为多个逻辑核心每个物理核下的逻辑核共用 L1/L2 Cache。而 Redis Server 除了主线程服务客户端请求之外还会创建子进程、子线程。其中子进程用于数据持久化而子线程用于执行一些比较耗时操作例如异步释放 fd、异步 AOF 刷盘、异步 lazy-free 等等。如果你把 Redis 进程只绑定了一个 CPU 逻辑核心上那么当 Redis 在进行数据持久化时fork 出的子进程会继承父进程的 CPU 使用偏好。而此时的子进程会消耗大量的 CPU 资源进行数据持久化把实例数据全部扫描出来需要耗费CPU这就会导致子进程会与主进程发生 CPU 争抢进而影响到主进程服务客户端请求访问延迟变大。这就是 Redis 绑定 CPU 带来的性能问题。那如何解决这个问题呢如果你确实想要绑定 CPU可以优化的方案是不要让 Redis 进程只绑定在一个 CPU 逻辑核上而是绑定在多个逻辑核心上而且绑定的多个逻辑核心最好是同一个物理核心这样它们还可以共用 L1/L2 Cache。当然即便我们把 Redis 绑定在多个逻辑核心上也只能在一定程度上缓解主线程、子进程、后台线程在 CPU 资源上的竞争。因为这些子进程、子线程还是会在这多个逻辑核心上进行切换存在性能损耗。如何再进一步优化可能你已经想到了我们是否可以让主线程、子进程、后台线程分别绑定在固定的 CPU 核心上不让它们来回切换这样一来他们各自使用的 CPU 资源互不影响。其实这个方案 Redis 官方已经想到了。Redis 在 6.0 版本已经推出了这个功能我们可以通过以下配置对主线程、后台线程、后台 RDB 进程、AOF rewrite 进程绑定固定的 CPU 逻辑核心# Redis Server 和 IO 线程绑定到 CPU核心 0,2,4,6 server_cpulist 0-7:2# 后台子线程绑定到 CPU核心 1,3 bio_cpulist 1,3# 后台 AOF rewrite 进程绑定到 CPU 核心 8,9,10,11 aof_rewrite_cpulist 8-11# 后台 RDB 进程绑定到 CPU 核心 1,10,11 # bgsave_cpulist 1,10-1 如果你使用的正好是 Redis 6.0 版本就可以通过以上配置来进一步提高 Redis 性能。这里我需要提醒你的是一般来说Redis 的性能已经足够优秀除非你对 Redis 的性能有更加严苛的要求否则不建议你绑定 CPU。从上面的分析你也能看出绑定 CPU 需要你对计算机体系结构有非常清晰的了解否则谨慎操作。我们继续分析还有什么场景会导致 Redis 变慢。使用Swap如果你发现 Redis 突然变得非常慢每次的操作耗时都达到了几百毫秒甚至秒级那此时你就需要检查 Redis 是否使用到了 Swap在这种情况下 Redis 基本上已经无法提供高性能的服务了。什么是 Swap为什么使用 Swap 会导致 Redis 的性能下降如果你对操作系统有些了解就会知道操作系统为了缓解内存不足对应用程序的影响允许把一部分内存中的数据换到磁盘上以达到应用程序对内存使用的缓冲这些内存数据被换到磁盘上的区域就是 Swap。问题就在于当内存中的数据被换到磁盘上后Redis 再访问这些数据时就需要从磁盘上读取访问磁盘的速度要比访问内存慢几百倍尤其是针对 Redis 这种对性能要求极高、性能极其敏感的数据库来说这个操作延时是无法接受的。此时你需要检查 Redis 机器的内存使用情况确认是否存在使用了 Swap。你可以通过以下方式来查看 Redis 进程是否使用到了 Swap# 先找到 Redis 的进程 ID $ ps -aux | grep redis-server# 查看 Redis Swap 使用情况 $ cat /proc/$pid/smaps | egrep ^(Swap|Size) 输出结果如下Size:               1256 kB Swap:                  0 kB Size:                  4 kB Swap:                  0 kB Size:                132 kB Swap:                  0 kB Size:              63488 kB Swap:                  0 kB Size:                132 kB Swap:                  0 kB Size:              65404 kB Swap:                  0 kB Size:            1921024 kB Swap:                  0 kB ... 这个结果会列出 Redis 进程的内存使用情况。每一行 Size 表示 Redis 所用的一块内存大小Size 下面的 Swap 就表示这块 Size 大小的内存有多少数据已经被换到磁盘上了如果这两个值相等说明这块内存的数据都已经完全被换到磁盘上了。如果只是少量数据被换到磁盘上例如每一块 Swap 占对应 Size 的比例很小那影响并不是很大。如果是几百兆甚至上 GB 的内存被换到了磁盘上那么你就需要警惕了这种情况 Redis 的性能肯定会急剧下降。此时的解决方案是增加机器的内存让 Redis 有足够的内存可以使用整理内存空间释放出足够的内存供 Redis 使用然后释放 Redis 的 Swap让 Redis 重新使用内存释放 Redis 的 Swap 过程通常要重启实例为了避免重启实例对业务的影响一般会先进行主从切换然后释放旧主节点的 Swap重启旧主节点实例待从库数据同步完成后再进行主从切换即可。可见当 Redis 使用到 Swap 后此时的 Redis 性能基本已达不到高性能的要求你可以理解为武功被废所以你也需要提前预防这种情况。预防的办法就是你需要对 Redis 机器的内存和 Swap 使用情况进行监控在内存不足或使用到 Swap 时报警出来及时处理。碎片整理Redis 的数据都存储在内存中当我们的应用程序频繁修改 Redis 中的数据时就有可能会导致 Redis 产生内存碎片。内存碎片会降低 Redis 的内存使用率我们可以通过执行 INFO 命令得到这个实例的内存碎片率# Memory used_memory:5709194824 used_memory_human:5.32G used_memory_rss:8264855552 used_memory_rss_human:7.70G ... mem_fragmentation_ratio:1.45 这个内存碎片率是怎么计算的很简单mem_fragmentation_ratio used_memory_rss / used_memory。其中 used_memory 表示 Redis 存储数据的内存大小而 used_memory_rss 表示操作系统实际分配给 Redis 进程的大小。如果 mem_fragmentation_ratio 1.5说明内存碎片率已经超过了 50%这时我们就需要采取一些措施来降低内存碎片了。解决的方案一般如下如果你使用的是 Redis 4.0 以下版本只能通过重启实例来解决如果你使用的是 Redis 4.0 版本它正好提供了自动碎片整理的功能可以通过配置开启碎片自动整理但是开启内存碎片整理它也有可能会导致 Redis 性能下降。原因在于Redis 的碎片整理工作是也在主线程中执行的当其进行碎片整理时必然会消耗 CPU 资源产生更多的耗时从而影响到客户端的请求。所以当你需要开启这个功能时最好提前测试评估它对 Redis 的影响。Redis 碎片整理的参数配置如下# 开启自动内存碎片整理总开关 activedefrag yes# 内存使用 100MB 以下不进行碎片整理 active-defrag-ignore-bytes 100mb# 内存碎片率超过 10%开始碎片整理 active-defrag-threshold-lower 10 # 内存碎片率超过 100%尽最大努力碎片整理 active-defrag-threshold-upper 100# 内存碎片整理占用 CPU 资源最小百分比 active-defrag-cycle-min 1 # 内存碎片整理占用 CPU 资源最大百分比 active-defrag-cycle-max 25# 碎片整理期间对于 List/Set/Hash/ZSet 类型元素一次 Scan 的数量 active-defrag-max-scan-fields 1000 你需要结合 Redis 机器的负载情况以及应用程序可接受的延迟范围进行评估合理调整碎片整理的参数尽可能降低碎片整理期间对 Redis 的影响。网络带宽过载如果以上产生性能问题的场景你都规避掉了而且 Redis 也稳定运行了很长时间但在某个时间点之后开始操作 Redis 突然开始变慢了而且一直持续下去这种情况又是什么原因导致此时你需要排查一下 Redis 机器的网络带宽是否过载是否存在某个实例把整个机器的网路带宽占满的情况。网络带宽过载的情况下服务器在 TCP 层和网络层就会出现数据包发送延迟、丢包等情况。Redis 的高性能除了操作内存之外就在于网络 IO 了如果网络 IO 存在瓶颈那么也会严重影响 Redis 的性能。如果确实出现这种情况你需要及时确认占满网络带宽 Redis 实例如果属于正常的业务访问那就需要及时扩容或迁移实例了避免因为这个实例流量过大影响这个机器的其他实例。运维层面你需要对 Redis 机器的各项指标增加监控包括网络流量在网络流量达到一定阈值时提前报警及时确认和扩容。其他原因好了以上这些方面就是如何排查 Redis 延迟问题的思路和路径。除了以上这些还有一些比较小的点你也需要注意一下1) 频繁短连接你的业务应用应该使用长连接操作 Redis避免频繁的短连接。频繁的短连接会导致 Redis 大量时间耗费在连接的建立和释放上TCP 的三次握手和四次挥手同样也会增加访问延迟。2) 运维监控前面我也提到了要想提前预知 Redis 变慢的情况发生必不可少的就是做好完善的监控。监控其实就是对采集 Redis 的各项运行时指标通常的做法是监控程序定时采集 Redis 的 INFO 信息然后根据 INFO 信息中的状态数据做数据展示和报警。这里我需要提醒你的是在写一些监控脚本或使用开源的监控组件时也不能掉以轻心。在写监控脚本访问 Redis 时尽量采用长连接的方式采集状态信息避免频繁短连接。同时你还要注意控制访问 Redis 的频率避免影响到业务请求。在使用一些开源的监控组件时最好了解一下这些组件的实现原理以及正确配置这些组件防止出现监控组件发生 Bug导致短时大量操作 Redis影响 Redis 性能的情况发生。我们当时就发生过DBA 在使用一些开源组件时因为配置和使用问题导致监控程序频繁地与 Redis 建立和断开连接导致 Redis 响应变慢。3其它程序争抢资源最后需要提醒你的是你的 Redis 机器最好专项专用只用来部署 Redis 实例不要部署其他应用程序尽量给 Redis 提供一个相对「安静」的环境避免其它程序占用 CPU、内存、磁盘资源导致分配给 Redis 的资源不足而受到影响。总结好了以上就是我总结的在使用 Redis 过程中常见的可能导致延迟、甚至阻塞的问题场景以及如何快速定位和分析这些问题并且针对性地提供了解决方案。这里我也汇总成了思维导图方便你在排查 Redis 性能问题时快速地去分析和定位。这里再简单总结一下Redis 的性能问题既涉及到了业务开发人员的使用方面也涉及到了 DBA 的运维方面。作为业务开发人员我们需要了解 Redis 的基本原理例如各个命令执行的时间复杂度、数据过期策略、数据淘汰策略等从而更合理地使用 Redis 命令并且结合业务场景进行优化。作为 DBA 和运维人员需要了解 Redis 运行机制例如数据持久化、内存碎片整理、进程绑核配置。除此之外还需要了解操作系统相关知识例如写时复制、内存大页、Swap 机制等等。同时DBA 在部署 Redis 时需要提前对进行容量规划预留足够的机器资源还要对 Redis 机器和实例做好完善的监控这样才能尽可能地保证 Redis 的稳定运行。后记如果你能耐心地看到这里想必你肯定已经对 Redis 的性能调优有了很大的收获。你应该也发现了Redis 的性能问题涉及到的知识点非常广几乎涵盖了 CPU、内存、网络、甚至磁盘的方方面面同时你还需要了解计算机的体系结构以及操作系统的各种机制。从资源使用角度来看包含的知识点如下CPU 相关使用复杂度过高命令、数据的持久化都与耗费过多的 CPU 资源有关内存相关bigkey 内存的申请和释放、数据过期、数据淘汰、碎片整理、内存大页、内存写时复制都与内存息息相关磁盘相关数据持久化、AOF 刷盘策略也会受到磁盘的影响网络相关短连接、实例流量过载、网络流量过载也会降低 Redis 性能计算机系统CPU 结构、内存分配都属于最基础的计算机系统知识操作系统写时复制、内存大页、Swap、CPU 绑定都属于操作系统层面的知识没想到吧Redis 为了把性能做到极致涉及到了这么多项优化。如果这篇文章内容你能吸收 90% 以上说明你对 Redis 原理、计算机基础、操作系统都已经有了较为深刻的理解。如果你能吸收 50% 左右那你可以好好梳理一下哪些方面是自己的知识盲区这样可以针对性地去学习。如果你吸收的只在 30% 以下那么你可以先从 Redis 的基本原理出发先了解 Redis 的各种机制进而思考 Redis 为了提高性能为什么使用这些机制这些机制又是利用了计算机和操作系统的哪些特性去做的进而一步步地去扩充你的知识体系这是一个非常高效的学习路径。由于篇幅限制关于 Redis 的很多细节无法全部展开其实这篇文章提到的每一个导致 Redis 性能问题的场景如果展开来讲都可以写出一篇文章出来。例如关于 Redis 进程绑定 CPU以及操作系统使用 Swap其实这些还涉及到了非一致性内存访问 NUMA 架构的影响其中也有很多细节没有展开来讲。这篇文章主要站在一个宏观层面进行性能分析如果你想了解更多细节欢迎关注我的公众号我会在后续的文章中带你深度剖析 Redis 的运行原理以及产生性能问题的更多细节。看到这里如果你觉得这篇文章对你有所帮助的话麻烦帮忙点赞、在看、转发一下你的支持会激励我输出更高质量的文章非常感谢另外你可以把我的公众号设为「星标」这样当公众号文章更新时你会在第一时间收到推送消息避免错过我的文章更新。 往期推荐 《大厂内部资料》Redis 性能优化的 13 条军规全网首发硬核Redis总结看这篇就够了Redis的8大数据类型写的真好关注我每天陪你进步一点点
http://www.sadfv.cn/news/273305/

相关文章:

  • 市场体系建设司在官方网站郑州市
  • 无锡网站制作公司品牌网站建设-建站之路
  • 重庆网站建设费用哪里有做空包网站的
  • 推荐几个自学做衣服的网站免费crm下载
  • 南京市住宅建设总公司网站网站聚合页面模板
  • 腾讯企业邮箱格式seo广州工作好吗
  • 平面设计的基本流程是什么常用的seo查询工具
  • 画画外包网站中国互联网协会电话多少
  • 找别人做网站 自己管理县级门户网站建设运营成本
  • 企业宣传网站有哪些图派做网站
  • 网站开发算软件开发吗网站平台多少钱
  • 免费建立一个个人网站微信公众号文章排版设计
  • 建高铁站赚钱吗wordpress不使用缩略图
  • 建设网站最新动态政务信息化建设网站
  • 来宾建设网站企业网站建设国内外现状
  • 如何做哟个优惠券网站个人电子商务网站 制作
  • 网站设计案例公司网站内容营销
  • 鞍山制作公司网站的公司物联网设计
  • 大学生二手书网站开发需求东莞房价一览表
  • 重庆网站建设的公司哪家好企查查企业信息查询手机版下载
  • 备案网站ip腾讯云低代码开发平台
  • 直播网站开发百度推广销售
  • 游览有关小城镇建设的网站百度快照推广是什么意思
  • 建立平台网站需要花多少钱100个经典创意营销方案
  • 深圳网站建设公司麦服务推广软文范例
  • 电脑做服务器发布网站吗怎么开发小程序
  • 济南专业网站优化ui设计师的工作内容包括哪些
  • 哈尔滨网站建设价格低什么是网站和网页
  • html网站制作答辩ppt建筑木模板
  • 通桥小学的网站建设浙江创都建设有限公司网站