数据库和redis的一致性
之前的讲解,主要是在讲解redis如何支撑海量数据、高并发读写、高可用服务的架构
从这一讲开始,正式开始做业务系统的开发
商品详情页,缓存架构,90%是大量的业务(没有什么级数含量),10%最有级数含量的就是架构
1、上亿流量的商品详情页的多级缓存架构
采用三级缓存:nginx本地缓存+redis分布式缓存+tomcat 堆缓存的多级缓存架构
nginx 本地缓存
redis分布式缓存
tomcat web应用 堆缓存
实时性要求非常高的数据:库存(希望当库存变化的时候,尽可能更快将库存显示到页面上去,而不是等了很长时间,库存才反应到页面上去)
实时性要求不高的数据:商品的基本信息(名称、颜色、版本、规格参数、等等)
对于实时性较高的数据来说,采用MYSQL和redis缓存双写的方案,这样缓存的时效性最高
nginx+lua脚本
lua脚本作为代码,部署到nginx本地,做第一层的业务逻辑
2、多级缓存架构中每一层的意义
1)nginx本地缓存,扛的是热数据的高并发访问,大量的热数据的访问,即经常会访问的那些数据,就会被保留在nginx本地缓存内。
2)redis分布式缓存,扛的是很高的离散访问,支撑海量的数据,高并发的访问,高可用的服务
3)tomcat 堆缓存主要是扛redis大规模灾难的
3、最经典的缓存+数据库读写的模式:cache aside pattern
1)Cache Aside Pattern
读的时候,先读缓存,缓存没有的话,那么就读数据库,然后取出数据放入缓存
更新的时候,先删除缓存,再更新数据库
2)为什么是删除缓存,而不是更新缓存?
很多时候,复杂点的缓存场景,因为缓存有的时候,不简单是数据库中直接取出来的值,在更新操作较多的数据项上,访问到的几率还是比较少,没有必要每次进行更新的时候都对缓存进行修改
4、数据库与缓存双写,可能导致数据不一致的问题,围绕和结合实时性较高的库存服务,把数据库与缓存双写不一致的问题及其解决方案,给大家讲解一下
5、最初级的缓存不一致问题以及解决方案
问题:先修改数据库,再删除缓存,如果删除缓存失败了,那么会导致数据库中是新数据,缓存中是旧数据,数据出现不一致
解决思路:先删除缓存,再修改数据库,如果修改数据库失败了,那么数据库中是旧数据,缓存中是空的,因为读的时候缓存没有,则度数据库中的旧数据,然后更新到缓存中
6、比较复杂的数据不一致问题
数据发生了变更,先删除了缓存,然后要去修改数据库,此时还没修改,一个请求过来,去读缓存,发现缓存空了,去查询数据库,查到了修改前的旧数据,放到了缓存中
然后数据变更的程序完成了数据库的修改,则数据库和缓存中的数据不一样了。。。
7、高并发情况下数据一致性的解决方案——数据库与缓存更新与读取操作进行异步串行化
更新数据库的时候,根据数据库的唯一标识,将操作路由之后,发送到一个jvm内部的队列中
一个队列对应一个工作线程(根据商品ID取hash值并对队列个数取模值,确定入队信息)
每个工作线程串行拿到对应的操作,然后一条一条执行
这样的话,一个数据变更的操作,先执行,删除缓存,然后再去更新数据库,但是还没完成更新
此时如果一个读请求过来,读到了空的缓存,那么可以先将缓存更新的请求发送到队列中,此时会在队列中积压,然后同步等待缓存更新完成
这里有一个优化点,一个队列中,其实多个更新缓存请求串在一起是没有意义的,因此可以做过滤,如果发现队列中已经有一个更新缓存的请求了,
那么就不用再放个更新请求操作进去了,直接等待前面的更新操作请求完成即可。
8.高并发的场景下,该解决方案要注意的问题
1)读请求长时阻塞
如果缓存是空的,有两种情况,一是,数据库里本身就没有这条数据,这是可以判断一下该内存队列有没有数据库更新操作,如果没有数据库更新操作,说明这条数据可能压根就是空的,那么不用hang住,就返回空。
如果内存队列里,有这条商品的更新操作,hang一会儿,去等待那个操作快速完成,然后返回。
2)读请求并发量过高
3)多服务实例部署的请求路由
可能这个服务部署了多个实例,那么必须保证说,执行数据更新操作,以及执行缓存更新操作的请求,都通过nginx服务器路由到相同的服务实例上
Service1 Service2 Service3
对同一个商品的读写请求,全部路由到同一台机器上
nginx,hash路由的功能
4)热点商品的路由问题,导致请求的倾斜
万一某个商品的读写请求特别高,全部打到相同的机器的相同的队列里面去了,可能造成某台机器的压力过大
就是说,因为只有在商品数据更新的时候才会清空缓存,然后才会导致读写并发,所以更新频率不是太高的话,这个问题的影响并不是特别大
数据库和redis的一致性的更多相关文章
- Linux实战教学笔记45:NoSQL数据库之redis持久化存储(一)
第1章 redis存储系统 1.1 redis概述 REmote DIctionary Server(Redis)是一个基于key-value键值对的持久化数据库存储系统.redis和大名鼎鼎的Mem ...
- 非关系型数据库(NOSQL)-Redis
整理一波Redis 简介,与memcached比较 官网:http://redis.io Redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括 ...
- NoSQL数据库:数据的一致性
NoSQL数据库:数据的一致性 读取一致性 强一致性 在任何时间访问集群中任一结点,得到的数据结果一致: 用户一致性 对同一用户,访问集群期间得到的数据一致: 解决用户一致性:使用粘性会话,将会话绑定 ...
- python爬取大众点评并写入mongodb数据库和redis数据库
抓取大众点评首页左侧信息,如图: 我们要实现把中文名字都存到mongodb,而每个链接存入redis数据库. 因为将数据存到mongodb时每一个信息都会有一个对应的id,那样就方便我们存入redis ...
- 数据库之redis篇(3)—— Python操作redis
虽然前面两篇已经说了redis的一些配置安装什么的,篇幅有点长,可能看完了也不知道怎么操作,这里再浓缩一下: 什么是redis redis完全开源免费的,遵守BSD协议,是一个高性能的非关系型key- ...
- 阿里云、青云、腾讯云服务器,Mysql数据库,Redis等产品性能对比
阿里云.青云.腾讯云服务器,Mysql数据库,Redis等产品都使用过,对比维度很多就不一一放出.直接放结论吧:买的腾讯(金融专区)服务器,Mysql(TDSql)把所有项目转到腾讯云,但是没有用腾讯 ...
- Python操作nosql数据库之redis
一.NoSQL的操作 NoSQL,泛指非关系型的数据库.随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不 ...
- key-value键值型数据库:Redis
key-value键值型数据库:Redis redis Redis是in-memory型(内存型)的键值数据库,数据在磁盘上是持久的,键类型是字符串,值类型是字符串.字符串集合(Set).sorted ...
- NOSQL数据库之 REDIS
NOSQL数据库之 REDIS 一.NOSQL 1.简介 NoSQL ,(Not Only SQL),泛指非关系型数据库. 特点: NoSQL 通常是以key-value形式存储, 不支持SQL语句, ...
随机推荐
- MI04 盘点单数据录入
*&---------------------------------------------------------------------* *& Report ZRHSSD002 ...
- Oracle用户密码认证方式
oracle用户有两种认证方式: 操作系统认证(要求该用户属于本地DBA组,然后通过操作系统认证登录oracle,从而启动数据库) 密码文件认证 oracle使用哪种认证方式决定在于两个参数: 1.r ...
- #pragma 处理警告 clang diagnostic 的使用
首先#pragma在本质上是声明,常用的功能就是注释,尤其是给Code分段注释:而且它还有另一个强大的功能是处理编译器警告,但却没有上一个功能用的那么多. clang diagnostic 是#pra ...
- API验证插件
前言 如果在访问某WebAPI过程中request信息被他人截获,若是get请求获取数据还好,如果是post提交数据,势必威胁数据安全,所以对于一个对安全性要求较高的API来说,对每个请求做身份验证显 ...
- Qt_qwt图形开发
QWT,全称是Qt Widgets for Technical Applications,是一个基于LGPL版权协议的开源项目, 可生成各种统计图.它为具有技术专业背景的程序提供GUI组件和一组实用类 ...
- for循环跳转语句(break、continue)
跳转语句用于实现循环执行过程中程序流程的跳转,在Java中的跳转语句有break语句和continue语句.接下来分别进行详细地讲解. 1. break语句 在switch条件语句和循环语句中都可以使 ...
- js重写系统的弹框
//调用系统的弹框,不显示地址 window.alert = function(name){ var iframe = document.createElement("IFRAME& ...
- bzoj2301
题解: 莫比乌斯反演 再加上一个分块 然后和上一题差不多了 代码: #include<cstdio> #include<cmath> #include<algorithm ...
- 主机访问虚拟机centos7的服务器
一.虚拟机开启桥梁接 1.编辑-->虚拟网络编辑器 2.虚拟机-->设置 二.Centos的配置---关闭防火墙下的服务器接口 Centos7.0 默认使用firewall作为防火墙,这里 ...
- 5.10 C++内存管理操作符重载
参考:http://www.weixueyuan.net/view/6388.html 注意: 内存管理操作符new.new[].delete和delete[]同样也可以进行操作符重载,其重载形式既可 ...