Redis高并发处理常见问题及解决方案
1. 大型电商系统高流量系统设计
场景:
大量电商系统每天要处理上亿请求,其中大量请求来自商品访问、下单。商品的详情是时刻变化,由于请求量过大,不会频繁去服务端获取商品信息,导致服务器压力极大。需要用到多级缓存、异步处理、负载均衡等方式来实现
解决:
评估哪些页面是活跃的,即用户查看使用较多的页面。页面里面包括静态资源和数据、动态数据等,划分层次,把静态资源存放到负载均衡服务器中缓存,如Nginx本地缓存。页面中的动态数据分为热点数据、非热点数据、实时数据、非实时数据等。把非热点数据、热点数据、非实时数据存放到Varnish缓冲中,Varnish擅长存储不变或变动较少的数据,通过Varnish的缓存策略,减少请求后端服务器的频率
Redis缓存存储热点数据、实时数据,Redis擅长存储需要原子操作计算、全局主键生成、订单号生成、排序相关数据。高并发情况下实时的数据处理讲究快速响应,为了提高效率可以采用异步消息队列处理。
系统架构采用了Nginx本地缓存、Http加速Varnish缓存、后端Redis缓存、消息队列等。注意:Nginx缓存静态资源、Varnish缓存不变或变动较少的数据、Redis缓存原子操作计算数据,异步队列主要处理非实时的业务或数据
2. Redis支撑百万QPS高并发、高可用架构
场景:
大型电商系统每天有上亿请求,会用到多级缓存,此时Redis单体无法承载需求量,需要使用Redis集体模式,由多态Redis共同承载并供外界使用
解决:
Redis单体处理并发能力达到10多万,分析Redis的瓶颈在于确定是读还是写方面。如果在读取数据方面在瓶颈时,可以采用读写分离、主从方式,通过哨兵监控服务正常性。主节点用于写入数据,并同步数据至从节点,从节点可以部署多台,整体提高Redis的读取数据能力
Redis主从模式:Redis集群主从部署,一台主节点写入,多台从节点读取,主节点数据同步到从节点,数据延迟毫秒级别,同时引入哨兵模式监控,当主节点宕机后,进行选主操作,到从节点选举一台升级为主节点,履行主节点的使命,当之前宕机的主节点恢复后,会加入到节点继续服务
如果在写方面存在瓶颈,可以采用Redis集群化,由多台Redis共同成立的虚拟组织机构共同提供外界写入、读取操作。Redis设置了合理的备份方案,防止数据丢失。集群化后的Redis可以提供上百万甚至上千万的QPS并发处理,集群部署
3. Redis雪崩后,备用方案
场景:
Redis集群模式中,由于网络、带宽等其他异常情况导致Redis雪崩后,如何提供网站正常服务并处理大量请求?设计时需要考虑到容灾,当Redis宕机后,监测到状态,启动其他缓存技术,如enCache、MemCache。注意,Redis和其他缓存之间需要定期同步数据,当Redis恢复后,切换到Redis
解决:
由于用户量、请求量都较多,设计时需考虑到极端情况,即要考虑替代方案。当Redis异常情况雪崩,系统监控到Redis心跳停止后,切换到备用缓存,如Memcache、Encache等,崩溃的Redis由于备份恰当,以尽快恢复使用,恢复期间可以用其他缓存,Redis使用期间的数据需要和崩溃后的数据进行同步,保证数据最终一致性,可以采用消息队列、备份文件对比复制等操作实现
> Web应用通过Lua脚本操作Redis时,发现其无心跳,会自动切换到其他缓存技术
4. 高并发情况下,数据库和缓存双写数据不一致问题
场景:
当核心业务需同时操作Redis和数据库时,由于两者之间存在非原子操作,当操作其中之一成功后出现异常、导致两者之间的数据不一致,应如何解决?可以引入异步消息队列串行化执行
解决:
1. 数据库先写入成功,Redis后写入失败
2. Redis先写入成功,数据库写入失败
3. 操作数据和Redis串行化,使用消息队列,由于其具有重试、吞吐量搞、消息持久化等特性个,可以通过消息队列来保证双写数据一致性。
先写入Mysql,加入消息队列,消费,写入Redis缓存,一致性。消费队列执行失败后,因为数据持久化,所以可以进行失败重试处理。
5. 高并发Redis缓存中的大value存储,全量更新时效率低
场景:
用户量不高,可能会把商品、详情等数据完全存储在Redis中某个key对应value中,随着用户量逐渐增加,此时处理更新时,处理效率比较差,可以按照存储信息的维度进行数据拆分,如商品信息可以按照商品的类别和批次进行拆分
解决:
由于Redis是单线程模式进行的,一次操作大的value会对整个Redis 的响应时间造成较大影响,所以业务上将其拆分成多个小key形式。可以按照功能的类别、批次维度进行拆分,建议每个key不要超过1MB
6. 高并发Redis防止缓存被穿透
场景:
当系统内使用缓存的地方的失效时间都一样时,若系统高峰期间恰好缓存失效了,大量请求至缓存中,此时都没命中,Redis的压力瞬间飙升,缓存被穿透。根据系统结构U划分,不同的操作需要设置不同的缓存失效时间,错开读取数据的时间,避免被穿透
解决:
高峰期间,系统受到诸多无效,如被攻击等,可在应用程序中使用Redis的常用方式来避免
处理流程如下:
1. 根据商品的主键goodID去缓存中查询商品,若商品存在即返回
2. 若商品不存在,再去查询数据库
3. 若数据库中存在,将其存储到Redis中,并设置过期时间
被击穿的情况:若高峰期间外界频繁去请求这个接口方法,传入的goodId有各种类型,此时去缓存中查询,大部分是没有数据的,然后这些请求会流入查询db中,Redis由于高性能特性可以去处理这部分请求,但是数据库中,由于数据库的连接数存在瓶颈,大量请求去查询数据库会导致数据库的CPU瞬间飙升,严重会卡死。
查询Redis为null,查询数据库也为null,此时设置该key在缓存中,且值为null,过期时间为随机时间。random(10)。这样子能保证数据在这段时间暴力请求,也只会在这短暂的时间内获取null,而有另外的线程在读取数据库表,并缓存在Redis中
7. 高并发Redis提高命中率
场景:
集群部署Redis中,由于多台Redis请求访问的频率存在不一致,导致Redis没有充分被利用,为了更好地提高访问次数和命中率,可以在部署策略中通过Lua脚本实现一致性Hash流量分发
解决:
命中:可以直接通过缓存获取数据
不命令:无法直接通过缓存获取数据,需要再次去数据库表中查询或者执行其他的操作。原因可能是由于缓存根本不存在或者缓存已过期
当缓存有过期的key存在时,会导致命中率下降。Redis中提供了info函数来监控服务器的状态,通过hits和miss计算命中率,14514119/(14514119+3428654)=82%,命中率较低,而一个良好的缓存存储机制包含了失效机制、过期时间设计,命中率高达95%以上
8. 高并发Redis防止雪崩
当Redis中的大量数据频繁过期失效后,可能有大量请求来获取数据,面临击穿,严重导致崩掉。可以用键值对失效时间合理设置、互斥锁等方式来防止雪崩
场景1:Redis缓存中,数据集体过期失效
在Redis缓存中的某个时间节点,缓存的数据集中过期失效,导致缓存被击穿,流量流向数据库中,造成数据库负载过高
场景2:Redis缓存中,Redis集群大批量机器故障
在Redis集群中大批量的机器故障,整体的稳定性和可靠性出现严重问题,不能给外界提供良好的服务,导致流量流向数据库,造成数据库负载过高
预防缓存雪崩解决:
1. 设计Redis缓存架构时,尽量设计高可用,防止大批量机器故障,当个别节点、部分机器出现问题后,不影响Redis整体的可用性
2. Redis缓存存储时,设计合理过期时间,错开业务交叉存储。合理的过期时间可以更大程度调高缓存的命中率,减少数据库的压力
9. 高并发Redis缓存预热方案
场景:
当系统热点数据初始化被高频率访问时,严重会造成阻塞死锁。可以在系统启动时预加载到缓存中
解决:
系统启动和核心功能使用之前进行缓存加载,如省市区、热点数据,这些数据更新频率较低,数据量较大,可以提前加载到容器中,当外界需要使用时,直接从缓存中,不需要查询数据库。那么当数据更新时如何更新缓存呢?
更新缓存有两种模式:自动和手动。手动即人工触发更新操作,把更新的数据流向缓存中。当缓存过期或失效后,可自动读取数据库数据然后加载到缓存中。为了保证缓存的充分利用,建议将更新频率较低的热点数据设置为永不过期,当数据改变时,可以用监听通知等方式自动更新缓存的数据
10. 高并发Redis缓存击穿
场景:
系统缓存中热点的数据某个时间点即将过期,恰好这个时间节点访问量突增,对于这个Key有大量的并发读取操作,这时候击穿了Redis,直接访问到DB中,会对DB形成巨大压力。可以设置热点数据永不过期,热点数据增加互斥锁
解决:
通常Redis中会优先存储热点数据,由于热点数据访问频率高,命中率会显著提高。高并发中,热点数据被频繁访问,当缓存热点数据恰好过期,大并发请求集中访问,持续的访问会直接击穿缓存,使流量直接流向数据库,给数据库造成较大压力。那么如何防止被击穿呢?简单可以设置热点数据永不过期,当热点数据发生更新时,通过监听通知等方式,自动更新缓存数据
11. 高并发Redis缓存集中失效
场景:
缓存中由于存储的数据过期时间固定且一样,导致同时间数据过期,缓存被穿透甚至雪崩。可以合理设置不同类型的缓存时间,如基于随机过期的缓存失效时间
解决:
Redis过期时间会直接影响命中率,为了提高命中率,需要合理设置过期失效,过期时间设置需要分类,包括热点数据、冷数据、临时数据等
1. 针对热点数据设置合理过期时间,需要从用户行为统计分析、物品模型的数据存储、物品被查看的次数等方面综合考虑,设定一个合理的数值,建议可设长点
2. 冷数据,一般被查看的次数、使用的频率较低,为了提高Redis整体的空间存储,通常冷数据设置的过期时间较短
3. 临时数据,即无效或者临时使用的数据,为了避免缓存被穿透,通常设置一个临时数据,过期时间设置较短
12. Redis高效拆分数据过程
场景:
系统构建初期使用单台Redis提供服务,发展过快,用户数量随之增加,此时单台Redis数据量过大,效率低下,会涉及Redis数据拆分迁移
解决:
以Redis数据拆分为例,RedisA存在用户、产品、订单数据,可拆分成RedisA、RedisB、RedisC,分别存放用户、产品、订单数据。针对RedisA 、RedisB、RedisC还可以进行父子Master-Slave方式进行扩展,假如其配置是32G,按照5K条数据1MB,保守可以存储2~3亿数据
Redis高并发处理常见问题及解决方案的更多相关文章
- Redis常见问题及解决方案
在Redis的运维使用过程中你遇到过那些问题,又是如何解决的呢?本文收集了一些Redis的常见问题以及解决方案,与大家一同探讨. 码字不易,欢迎大家转载,烦请注明出处:谢谢配合 你的Redis有big ...
- redis常见问题和解决方案
转载:https://www.cnblogs.com/aspirant/p/6820262.html [原创]那些年用过的Redis集群架构(含面试解析) redis常见问题和解决方案 持久化.主从问 ...
- 高并发架构系列:Redis并发竞争key的解决方案详解
https://blog.csdn.net/ChenRui_yz/article/details/85096418 https://blog.csdn.net/ChenRui_yz/article/l ...
- Redis 高并发解决方案
针对大流量瞬间冲击,比如秒杀场景 redis前面可以加一层限流 sentinel / Hystrix redis高并发(读多写少)下缓存数据库双写误差: 1. 修改操作使用分布式锁(就是修改的时候加锁 ...
- akka框架——异步非阻塞高并发处理框架
akka actor, akka cluster akka是一系列框架,包括akka-actor, akka-remote, akka-cluster, akka-stream等,分别具有高并发处理模 ...
- java并发编程笔记(十一)——高并发处理思路和手段
java并发编程笔记(十一)--高并发处理思路和手段 扩容 垂直扩容(纵向扩展):提高系统部件能力 水平扩容(横向扩容):增加更多系统成员来实现 缓存 缓存特征 命中率:命中数/(命中数+没有命中数) ...
- Keepalived+Redis高可用部署(第二版)
更新 20150625 脚本由5个减少为4个,sh脚本指令做了精简. 修改了另外3个脚本,在日志里增加了日期显示. 新增redis数据类型,持久化,主从同步简介. 新增hiredis简介. 新增c语言 ...
- 常用数据库高可用和分区解决方案(1) — MySQL篇
在本文中我们将会讨论MySQL.Oracle.MongoDB.Redis以及Oceanbase数据库,大家可能会奇怪为什么看不到有名关系型数据库MSSQL.DB2或者有名NoSQL数据库Hbase.L ...
- XHTML CSS 常见问题和解决方案
原文地址:XHTML CSS 常见问题和解决方案 作为前端开发人员,在日常的页面制作时,不可避免的会碰上这样那样的问题,我挑选了其中的一些进行总结归档,希望对大家会有所帮助: 1.如何定义高度很小的容 ...
随机推荐
- Microsoft Porject Online 学习随手记一:环境创建和数据导入
没有想像的简单,也没那么复杂 Project OL之前是Dynamics 365 Enterprise P1中的一个模块,目前最新版本只能简单创建并且已经没有Enterprise P1选项. 主要流程 ...
- 写了10000条Airtest截图脚本总结出来的截图经验,赶紧收藏!
前言 今天想先给大家分享1个小白用户的Airtest从入门到放弃的故事: 小A是一个自动化的小白,在逛测试论坛的时候,偶然间发现了Airtest这个基于图像识别的UI自动化框架. 出于好奇,小A试用了 ...
- 记一次 .NET 某资讯论坛 CPU爆高分析
大概有11天没发文了,真的不是因为懒,本想前几天抽空写,不知道为啥最近求助的朋友比较多,一天都能拿到2-3个求助dump,晚上回来就是一顿分析,有点意思的是大多朋友自己都分析了几遍或者公司多年的牛皮藓 ...
- OO第四单元UML作业总结暨OO课程总结
目录 目录一.第四单元UML两次作业架构设计第一次作业第二次作业二.架构设计总结与OO方法理解演进三.测试理解与实践演进四.课程收获总结五.课程改进建议六.尾声 一.第四单元UML两次作业架构设计 第 ...
- Noip模拟16 2021.7.15
题目真是越来越变态了 T1 Star Way To Heaven 首先,你要看出这是一个最小生成树的题(妙吧?) 为什么可以呢? 我们发现从两点连线的中点过是最优的,但是上下边界怎么办呢? 我们把上下 ...
- 『学了就忘』Linux基础 — 14、Linux系统的设备文件名和挂载
目录 1.设备文件名 (1)为什么需要设备文件名 (2)硬件设备文件名命名规则 2.挂载点 3.挂载 (1)什么是挂载 (2)挂载前的分区要求 (3)小结(重点) 1.设备文件名 (1)为什么需要设备 ...
- PHP笔记4__函数/全局、静态变量/函数参数/加载函数库/,,
<?php header("Content-type: text/html; charset=utf-8"); echo table(5,5); function table ...
- $.ajax、$.get和$.post方法成功,完成请求,错误或失败的回调
一.$.get和$.post的不同 1.get通过url提交的,post是通过http消息实体提交的 2.get提交大小限制为2kb,post不限制 3.get提交会被缓存下来,有安 ...
- 编译安装与gcc编译器
先说一下gcc编译器,只知道这是一个老款的编译器.编译的目的也比较重要,就是将c语言的代码编译成可以执行的binary文件. gcc 简单使用(后期补充) eg: gcc example.c # ...
- Docker安装配置Tomcat
1.使用docker pull tomcat下载镜像(不加tag则是下载最新版本) 2.运行容器(-d 后台运行:-p 指定端口映射),接的是镜像ID 3.进入容器执行命令,接的是容器ID 4.宿主机 ...