为什么说阻塞是Redis的噩梦:

  Redis是典型的单线程架构,所有的读写操作都是在一条主线程中完成的。当Redis用于高并发场景时,这条线程就变成了它的生命线。如果出现阻塞,哪怕是很短时间,对于应用来说都是噩梦。

  导致阻塞问题的原因:

  • 内在原因:不合理地使用API或数据结构、CPU饱和、持久化阻塞等
  • 外在原因:CPU竞争、内存交换、网络问题等

  一、发现阻塞

  • 应用方加入异常监控,如日志系统,比如Java语言中的logback或log4j
  • Redis监控系统,如CacheCloud

  二、内在原因

  1.API或数据结构使用不合理

  通常Redis执行命令速度非常快,但是,如果对一个包含上万个元素的hash结构执行hgetall操作,由于数据量比较大且命令算法复杂度是O(n),这条命令执行速度必然很慢。

  对于高并发的场景应该尽量避免在大对象上执行算法复杂度超过O(n)的命令。

  (1)如何发现慢查询

  Redis原生提供慢查询统计功能,执行slowlog get{n}命令可以获取最近的n条慢查询命令,默认对于执行超过10毫秒的命令都会记录到一个定长队列中,线上实例建议设置为1毫秒便于及时发现毫秒级以上的命令。

  (2)发现慢查询后如何调整

  • 修改为低算法复杂度的命令
  • 调整大对象:缩减大对象数据或把大对象拆分为多个小对象,防止一次命令操作过多的数据。大对象拆分过程需要视具体的业务决定,如用户好友集合存储在Redis中,有些热点用户会关注大量好友,这时可以按时间或其他维度拆分到多个集合中。

  (3)如何发现大对象

bigjun@myubuntu:~$ redis-cli -h 192.168.131.130 -p 6379 --bigkeys# Scanning the entire keyspace to find biggest keys as well as
# average sizes per key type.  You can use -i 0.1 to sleep 0.1 sec
# per 100 SCAN commands (not usually needed).[00.00%] Biggest string found so far 'XML' with 180 bytes
[00.00%] Biggest list   found so far 'hot:user:list' with 5 items-------- summary -------Sampled 12 keys in the keyspace!
Total key length in bytes is 108 (avg len 9.00)Biggest string found 'XML' has 180 bytes
Biggest   list found 'hot:user:list' has 5 items11 strings with 480 bytes (91.67% of keys, avg size 43.64)
1 lists with 5 items (08.33% of keys, avg size 5.00)
0 sets with 0 members (00.00% of keys, avg size 0.00)
0 hashs with 0 fields (00.00% of keys, avg size 0.00)
0 zsets with 0 members (00.00% of keys, avg size 0.00)
0 streams with 0 entries (00.00% of keys, avg size 0.00)

  2.CPU饱和

  单线程的Redis处理命令时只能使用一个CPU。而CPU饱和是指Redis把单核CPU使用率跑到接近100%。使用top命令很容易识别出对应Redis进程的CPU使用率。CPU饱和是非常危险的,将导致Redis无法处理更多的命令,严重影响吞吐量和应用方的稳定性。对于这种情况,首先判断当前Redis的并发量是否达到极限,建议使用统计命令redis-cli -h {ip} -p {port} --stat获取当前Redis使用情况

bigjun@myubuntu:~$ redis-cli -h 192.168.131.130 -p 6379 --stat
------- data ------ --------------------- load -------------------- - child -
keys       mem      clients blocked requests            connections
12         851.05K  2       0       506 (+0)            15
12         851.05K  2       0       507 (+1)            15
12         851.05K  2       0       508 (+1)            15
12         851.05K  2       0       509 (+1)            15
12         851.05K  2       0       510 (+1)            15
12         851.05K  2       0       511 (+1)            15
12         851.05K  2       0       512 (+1)            15
12         851.05K  2       0       513 (+1)            15
12         851.05K  2       0       514 (+1)            15   ...

  然后根据info commandstats统计信息分析出命令不合理开销时间:

192.168.131.130:6379> info commandstats
# Commandstats
cmdstat_type:calls=12,usec=3,usec_per_call=0.25
cmdstat_scan:calls=2,usec=17,usec_per_call=8.50
cmdstat_monitor:calls=1,usec=1,usec_per_call=1.00
cmdstat_del:calls=1,usec=70,usec_per_call=70.00
cmdstat_mset:calls=1,usec=34,usec_per_call=34.00
cmdstat_replconf:calls=398,usec=985,usec_per_call=2.47
cmdstat_llen:calls=1,usec=0,usec_per_call=0.00
cmdstat_script:calls=7,usec=809,usec_per_call=115.57
cmdstat_incr:calls=5,usec=33,usec_per_call=6.60
cmdstat_rpush:calls=1,usec=41,usec_per_call=41.00
cmdstat_dbsize:calls=1,usec=1,usec_per_call=1.00
cmdstat_client:calls=12,usec=189,usec_per_call=15.75
cmdstat_bgsave:calls=1,usec=296,usec_per_call=296.00
cmdstat_get:calls=9,usec=95,usec_per_call=10.56
cmdstat_eval:calls=11,usec=90262859,usec_per_call=8205714.00
cmdstat_lrange:calls=3,usec=114,usec_per_call=38.00
cmdstat_set:calls=3,usec=63,usec_per_call=21.00
cmdstat_keys:calls=10,usec=409,usec_per_call=40.90
cmdstat_strlen:calls=11,usec=15,usec_per_call=1.36
cmdstat_save:calls=1,usec=1410,usec_per_call=1410.00
cmdstat_evalsha:calls=1,usec=20,usec_per_call=20.00
cmdstat_info:calls=14,usec=1005,usec_per_call=71.79
cmdstat_ping:calls=4,usec=5,usec_per_call=1.25
cmdstat_command:calls=2,usec=560,usec_per_call=280.00
cmdstat_mget:calls=2,usec=18,usec_per_call=9.00
cmdstat_psync:calls=1,usec=1608,usec_per_call=1608.00

  3.持久化阻塞

  对于开启了持久化功能的Redis节点,需要排查是否是持久化导致的阻塞。

  • fork阻塞:ork操作发生在RDB和AOF重写时,Redis主线程调用fork操作产生共享内存的子进程,由子进程完成持久化文件重写工作。如果fork操作本身耗时过长,必然会导致主线程的阻塞。
  • AOF刷盘阻塞:当我们开启AOF持久化功能时,文件刷盘的方式一般采用每秒一次,后台线程每秒对AOF文件做fsync操作。当硬盘压力过大时,fsync操作需要等待,直到写入完成。如果主线程发现距离上一次的fsync成功超过2秒,为了数据安全性它会阻塞直到后台线程执行fsync操作完成。这种阻塞行为主要是硬盘压力引起。
  • HugePage写操作阻塞:子进程在执行重写期间利用Linux写时复制技术降低内存开销,因此只有写操作时Redis才复制要修改的内存页。对于开启Transparent HugePages的操作系统,每次写命令引起的复制内存页单位由4K变为2MB,放大了512倍,会拖慢写操作的执行时间,导致大量写操作慢查询。

  三、外在原因

  1.CPU竞争

  • 进程竞争:Redis是典型的CPU密集型应用,不建议和其他多核CPU密集型服务部署在一起。当其他进程过度消耗CPU时,将严重影响Redis吞吐量。可以通过top、sar等命令定位到CPU消耗的时间点和具体进程,这个问题比较容易发现,需要调整服务之间部署结构。
  • 绑定CPU:部署Redis时为了充分利用多核CPU,通常一台机器部署多个实例。常见的一种优化是把Redis进程绑定到CPU上,用于降低CPU频繁上下文切换的开销。这个优化技巧正常情况下没有问题,但是存在例外情况,当Redis父进程创建子进程进行RDB/AOF重写时,如果做了CPU绑定,会与父进程共享使用一个CPU。子进程重写时对单核CPU使用率通常在90%以上,父进程与子进程将产生激烈CPU竞争,极大影响Redis稳定性。因此对于开启了持久化或参与复制的主节点不建议绑定CPU。

  2.内存交换

  内存交换(swap)对于Redis来说是非常致命的,Redis保证高性能的一个重要前提是所有的数据在内存中。如果操作系统把Redis使用的部分内存换出到硬盘,由于内存与硬盘读写速度差几个数量级,会导致发生交换后的Redis性能急剧下降。

  (1)识别内存交换:

bigjun@myubuntu:~$ redis-cli -h 192.168.131.130 -p 6379 info server | grep process_id
process_id:2668root@myubuntu:~# cat /proc/2668/smaps  | grep Swap
Swap:                  0 kB
SwapPss:               0 kB
Swap:                  0 kB
SwapPss:               0 kB
Swap:                  0 kB
SwapPss:               0 kB
Swap:                  0 kB
SwapPss:               0 kB
...

  (2)预防内存交换:

  • 保证机器充足的可用内存。
  • 确保所有Redis实例设置最大可用内存(maxmemory),防止极端情况下Redis内存不可控的增长。
  • 降低系统使用swap优先级。

  3.网络问题

  (1)连接拒绝

  • 网络闪断(网络割接或者带宽耗尽)
  • Redis连接拒绝(超过客户端最大连接数)
  • 连接溢出(进程限制或backlog队列溢出)

  (2)网络延迟

  网络延迟取决于客户端到Redis服务器之间的网络环境。主要包括它们之间的物理拓扑和带宽占用情况。常见的物理拓扑按网络延迟由快到慢可分为:同物理机>同机架>跨机架>同机房>同城机房>异地机房。但它们容灾性正好相反,同物理机容灾性最低而异地机房容灾性最高。

  网络延迟问题经常出现在跨机房的部署结构上,对于机房之间延迟比较严重的场景需要调整拓扑结构,如把客户端和Redis部署在同机房或同城机房等。
  带宽瓶颈通常出现在以下几个方面:

  • 机器网卡带宽。
  • 机架交换机带宽。
  • 机房之间专线带宽。

  (3)网卡软中断

  网卡软中断是指由于单个网卡队列只能使用一个CPU,高并发下网卡数据交互都集中在同一个CPU,导致无法充分利用多核CPU的情况。网卡软中断瓶颈一般出现在网络高流量吞吐的场景。

转载于:https://www.cnblogs.com/BigJunOba/p/9136099.html

Redis(七)Redis的噩梦:阻塞相关推荐

  1. 深入剖析Redis系列(七) - Redis数据结构之列表

    前言 列表(list)类型是用来存储多个 有序 的 字符串.在 Redis 中,可以对列表的 两端 进行 插入(push)和 弹出(pop)操作,还可以获取 指定范围 的 元素列表.获取 指定索引下标 ...

  2. redis:redis介绍和安装、普通连接和连接池、redis 5大数据类型之字符串、Hash、列表、其他操作(通用)、管道、django使用redis、接口缓存

    目录 一. redis介绍和安装 二. 普通连接和连接池 三. redis 5大数据类型之字符串 四. redis 5大数据类型之Hash 五. redis 5大数据类型之列表 六. 其他操作(通用) ...

  3. 【Redis】Redis基础知识点

    Redis基础知识点 简介.Memcache和Redis.多路I/O复用 常用数据类型 海量数据中筛选某一固定前缀的key 实现简单的分布式锁 实现异步队列 持久化:RDB.AOF.混合 Pipeli ...

  4. 【檀越剑指大厂--redis】redis高阶篇

    一.数据结构与对象 1.什么是 SDS? Redis 没有直接使用 C 语言传统的字符吕表示 (以空字符结尾的字符数组,以下简称 C 字符串),而是自己构建了 一种名为简单动态字符串(simple d ...

  5. 【带你重拾Redis】Redis持久化

    Redis持久化 Redis有2种持久化策略: RDB和AOF. RDB(Redis Data Base) RDB是Redis默认的持久化策略,这种策略是把数据库的快照以二进制形式的副本保存在磁盘上. ...

  6. 【带你重拾Redis】Redis常见知识点

    什么是Redis? Redis是一个使用ANSI C语言编写,遵守BSD协议规范的开源的K-V类型的NoSQL数据库服务器. Redis是当前最流行的K-V类型的NoSQL数据库之一,在通往系统架构的 ...

  7. Redis、Redis+sentinel安装(Ubuntu 14.04下Redis安装及简单测试)

    Ubuntu下Redis安装两种安装方式: 1.apt-get方式 步骤: 以root权限登录,切换到/usr目录下. 接下来输入命令,apt-get install redis-server,如图: ...

  8. 初识redis(redis基础命令)

    redis简介 redis是一个开源(BSD许可)的使用C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,它可以用作数据库.缓存和消息中间件,并提供多种语言的API.从20 ...

  9. php连接redis 主从复制,redis怎么进行主从复制

    redis主从复制同步实现的过程 1.从服务发送一个sync同步命令给主服务要求全量同步 (推荐学习:Redis视频教程) 2.主服务接收到从服务的sync同步命令时,会fork一个子进程后台执行bg ...

  10. redis数据类型_认识Redis与Redis的数据类型

    本文作为Redis的入门教程,旨在让大家对Redis有一个概念性和整体性的认识,并且可以快速上手,为深入Redis打下基础. 文章概要: 1. Redis的介绍 2. Redis与其他数据库的对比 3 ...

最新文章

  1. 为什么不记录慢速查询?
  2. 易点租加速电脑租赁市场布局
  3. 2018年全国多校算法寒假训练营练习比赛(第二场)B - TaoTao要吃鸡
  4. php 数组美化_PHP格式化输出数组,一目了然
  5. WinForm数据源分页技术
  6. win32异常处理函数
  7. 微服务架构师的职责——《微服务设计读书笔记》
  8. 以太坊白皮书_以太坊发展历程
  9. 用计算机进行服装设计,电脑服装设计(10制版1班)
  10. jq 封装弹窗提示框,自动消失,确认
  11. DataGridView的Cell事件的先后触发顺序
  12. 基于Django的网上书城系统
  13. 医学图像有哪些会议期刊可以投
  14. 七大排序算法,冒泡排序 选择排序 插入排序 希尔排序 堆排序 快速排序 归并排序的深度讲解
  15. k8s多节点master部署
  16. 3D建模师的需求到底有多大?以前想都不敢想
  17. Java爬虫之jsoup的使用
  18. 读书笔记-《购物中心》
  19. m1卡读写c语言,Android NFC(一) M1卡读写
  20. 泛微E9-会议室使用情况中如何显示手机号、部门等字段

热门文章

  1. html页面加载转圈,纯CSS实现加载转圈样式
  2. 6 redhat 查看rtc时间_RTC 月度小报 9 月 | WebRTC M77、RTC大会即将开幕、实时码流加速...
  3. c++中有表示正无穷的数吗_简单的数
  4. diagram怎么记忆_UML20以上14图的解释、分类记忆方法及类之间6种关系
  5. java esp_在我的ESP游戏方法中非法开始表达
  6. php iframe 上传图片,利用iframe+php实现图片的上传
  7. 从零开始搭建spring-cloud(4) ----Hystrix
  8. jena fuseki RDF应用
  9. 送一台自用笔记本电脑!新款
  10. 你不就是加了 2 行代码,为什么要用 2 天?