nginx+redis+tomcat三级缓存架构讲解
来源:互联网 发布:社会主义生产方式知乎 编辑:程序博客网 时间:2024/06/07 21:20
对于一个大型的数据缓存系统,会部署多层缓存服务来达到高并发、高可用的系统需求
nginx层
对于传统的缓存系统,请求到达nginx,然后分发到对应的服务系统,然后查询redis中是否有数据,然后将结果返回,这里会花费很大的网络开销。nginx可以支持热数据的缓存,对这些数据直接缓存在nginx内存中,请求到来直接返回,不需要去发送网络请求。但是nginx内存的大小一般会很小,所以适合缓存热数据redis cluster层
这一层的数据是最完整的,大部分的离散请求都会访问到这一层。因此一定要做到高可用,可水平伸缩的模式tomcat层
tomcat中的堆也可以缓存一定的数据,但是容量也不会太大。主要是用来防止redis层大面积崩溃之后,大量数据请求直接到DB层
对于数据不同的实时性要求,我们可以采取不同的方式来修改缓存
对于实时性较高的数据(例如库存数据):
对于这种实时性很高的数据,当有修改的时候,一般是修改DB然后同时去修改redis缓存的双写模式。但是这里会设计到数据不一致的问题。
- 最初级不一致问题及解决方案
对于先修改数据库,再删除缓存,如果缓存删除失败,那么回导致数据库中是最新数据,缓存中是旧数据,出现不一致的情况。
解决方法:先删除缓存,再修改数据库 - 比较复杂的数据不一致问题
对于高并发的请求,读写操作可能会产生不一致的问题,在写的过程中,另一个读操作重新读取到来旧数据。当然对于并发不高的系统,这种情况也基本不会遇到。
解决方案如下:
数据库、缓存更新与读取操作进行异步串行化
将需要更新的数据,发送到jvm内部的队列中,一般会维护多个内存队列,对数据的唯一标识hash然后对内存队列数量取模,就可以保证同样的数据操作一定会在同一个队列中去。
每个队列有一个工作线程,每个工作线程串行拿到对应的操作,然后逐条执行。因此一个数据的变更,会先删除缓存,然后再去更新数据库,当还没有更新完成的时候,另一个读请求过来来,读到空的缓存,那么可以将这个缓存更新的请求发送到队列中,从而会同步等待缓存更新完成。需要注意的一点,对于缓存为空,多个读请求过来,将多个更新缓存的请求发送到队列是没有必要的,因此需要做过滤,然后可以将这些读请求hang住一个时间段,轮询去查询缓存,当前面队列中的更新缓存请求执行完成后,就可以拿到缓存数据直接返回,否则,可以让服务直接取查询DB来拿数据。
在高并发下,需要注意:
- 对于缓存中没有该数据,也可能是数据库本身就没有。因此需要判断队列中是否有更新该数据的操作,如果没有则读请求没有必要hang住,直接返回空即可
- 需要线上模拟压力测试,当内存队列积压过多的更新数据操作,会对最后的读操作产生于一定的延时,此时如果需要优化就需要加机器,分配到更平均的队列数量中
基于zookeeper分布式锁解决多服务缓存重建并发冲突:
对于多个缓存服务,可能存在这种情况,nginx请求到达发现都没有相应缓存数据,会发送请求给缓存服务到数据源拉取数据并写入相应tomcat/redis,同时kafka生产了消息的变更记录也需要去拉取数据并存入tomcat/redis。两者拉取数据源与缓存重建可能会出现并发冲突导致tomcat/redis中的最终数据并不是最新。
对于实时性不高的数据
对于实时性不高的数据,如果发生了变更,几分钟之后才更新到页面上,我们采取异步更新缓存的策略。缓存数据生产服务,监听一个消息队列,然后数据源服务(商品信息管理服务)发生来变更之后,就将数据变更的消息推送到消息队列(topic),缓存数据生产服务可以去消费这些变更的信息,然后根据消息的提示提取一些参数,然后调用对应的数据源服务接口拉取数据,一般是从mysql拉取,然后将数据存放到本地堆缓存和redis缓存
对于nginx层的缓存
一般来说,默认会部署多个nginx,在里面都会放一些缓存,此时缓存的命中率会非常底,因为对同样数据的请求可能被路由到多个nginx从而未能找到相应缓存而多次对redis发起请求。因此,可以采用分发层+应用层双层ngin来提升缓存命中率。
- 分发层nginx:负责流量分发的逻辑和策略,根据自己定义的一些规则,比如根据productId进行hash,然后对后端nginx数量取模将某一个商品的访问请求固定路由到一个nginx后端服务器上去,保证了nginx只会对该商品数据从redis获取一次。之后的同样商品请求都直接走nginx缓存。
- 后端nginx: 称之为应用服务器
- nginx+redis+tomcat三级缓存架构讲解
- Nginx安装,Nginx静态缓存,Nginx Gzip压缩,Nginx负载均衡,Nginx方向代理,Nginx+Tomcat+Redis做session共享
- Tomcat+redis+nginx配置
- Tomcat+redis+nginx配置
- nginx+tomcat+redis基本概念
- nginx+tomcat+redis
- 高性能网站架构之负载均衡 Nginx+tomcat+redis实现tomcat集群
- 高性能网站架构之负载均衡 Nginx+tomcat+redis实现tomcat集群
- 高性能网站架构之负载均衡 Nginx+tomcat+redis实现tomcat集群
- 高性能网站架构之负载均衡 Nginx+tomcat+redis实现tomcat集群
- 高性能网站架构之负载均衡 Nginx+tomcat+redis实现tomcat集群
- Nginx+Tomcat集群配置讲解
- Android自制图片的三级缓存(代码+讲解)
- tomcat+nginx+redis集群试验
- tomcat+redis+nginx session共享
- nginx + tomcat + redis问题记录
- windows nginx tomcat redis 集群
- Nginx+Tomcat+redis集群配置
- GDCA参加第42次CA/B论坛(CA/Browser Forum)国际工作会议
- 求解逆波兰表达式(Calculate the reverse Polish notation)。有关栈的最基础应用。
- NUnits 配置问题
- openjdk和jdk的区别
- windows环境下安装selenium
- nginx+redis+tomcat三级缓存架构讲解
- GML C++ Camera Calibration Toolbox 相机标定畸变矫正
- Springmvc学习(06)-异常处理
- VC控制excel
- 自定义View之RGB颜色变化Paint画笔颜色过滤器setColorFilter,LightingColorFilter光照过滤器
- 反射获取类的结构信息
- 使用Hexo和Github快速搭建个人博客
- Java并发编程:volatile关键字解析
- java判断string变量是否是数字的六种方法小结