之前的讲解,主要是在讲解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的一致性的更多相关文章

  1. Linux实战教学笔记45:NoSQL数据库之redis持久化存储(一)

    第1章 redis存储系统 1.1 redis概述 REmote DIctionary Server(Redis)是一个基于key-value键值对的持久化数据库存储系统.redis和大名鼎鼎的Mem ...

  2. 非关系型数据库(NOSQL)-Redis

    整理一波Redis 简介,与memcached比较 官网:http://redis.io Redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括 ...

  3. NoSQL数据库:数据的一致性

    NoSQL数据库:数据的一致性 读取一致性 强一致性 在任何时间访问集群中任一结点,得到的数据结果一致: 用户一致性 对同一用户,访问集群期间得到的数据一致: 解决用户一致性:使用粘性会话,将会话绑定 ...

  4. python爬取大众点评并写入mongodb数据库和redis数据库

    抓取大众点评首页左侧信息,如图: 我们要实现把中文名字都存到mongodb,而每个链接存入redis数据库. 因为将数据存到mongodb时每一个信息都会有一个对应的id,那样就方便我们存入redis ...

  5. 数据库之redis篇(3)—— Python操作redis

    虽然前面两篇已经说了redis的一些配置安装什么的,篇幅有点长,可能看完了也不知道怎么操作,这里再浓缩一下: 什么是redis redis完全开源免费的,遵守BSD协议,是一个高性能的非关系型key- ...

  6. 阿里云、青云、腾讯云服务器,Mysql数据库,Redis等产品性能对比

    阿里云.青云.腾讯云服务器,Mysql数据库,Redis等产品都使用过,对比维度很多就不一一放出.直接放结论吧:买的腾讯(金融专区)服务器,Mysql(TDSql)把所有项目转到腾讯云,但是没有用腾讯 ...

  7. Python操作nosql数据库之redis

    一.NoSQL的操作 NoSQL,泛指非关系型的数据库.随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不 ...

  8. key-value键值型数据库:Redis

    key-value键值型数据库:Redis redis Redis是in-memory型(内存型)的键值数据库,数据在磁盘上是持久的,键类型是字符串,值类型是字符串.字符串集合(Set).sorted ...

  9. NOSQL数据库之 REDIS

    NOSQL数据库之 REDIS 一.NOSQL 1.简介 NoSQL ,(Not Only SQL),泛指非关系型数据库. 特点: NoSQL 通常是以key-value形式存储, 不支持SQL语句, ...

随机推荐

  1. [CodeForces - 614A] A - Link/Cut Tree

    A - Link/Cut Tree Programmer Rostislav got seriously interested in the Link/Cut Tree data structure, ...

  2. 前端开发VScode常用插件

    名称 功能 Auto Close Tag 自动闭合HTML标签 Auto Import Typescript 自动import提示 Auto Rename Tag 修改HTML标签时,自动修改匹配的标 ...

  3. Windows与Linux的回车换行转换

    最初"\r"(return)表示“回车”即回到行首,“\n”(next)表示“换行”即定位到下一行:UNIX和Linux使用“\n”换行,而Windows用“\r\n”(不是\n\ ...

  4. 关于jsp页面的一些知识(一)

    1,<%@ include file=” ”%> ——最简洁易懂的解释 http://blog.csdn.net/little_stars/article/details/17373477 ...

  5. linux下查看物理CPU个数、核数、逻辑CPU个数

    cat /proc/cpuinfo中的信息 processor 逻辑处理器的id.physical id 物理封装的处理器的id.core id 每个核心的id.cpu cores 位于相同物理封装的 ...

  6. Java Web(九) JDBC及数据库连接池及DBCP,c3p0,dbutils的使用

    DBCP.C3P0.DBUtils的jar包和配置文件(百度云盘):点我下载 JDBC JDBC(Java 数据库连接,Java Database Connectify)是标准的Java访问数据库的A ...

  7. Laravel 更新数据时在表单请求验证中排除自己,检查指定字段唯一性

    原文地址:https://moell.cn/article/24 不错的laravel网站 需求场景 修改用户信息时,在表单请求验证中排除当前邮箱所在的记录行,并检查邮箱的唯一性. Laravel版本 ...

  8. Mybatis的二级缓存注意点

    --声明:一下内容都不一定是正确的,只是自己测试的结果,请自己的动手操作得出自己的结论 1.开启Mybatis的二级缓存,不仅要在SqlMapConfig.xml中进行开启总开关,还要在对应的XXXM ...

  9. JDBC:随机生成车牌号,批量插入数据库

    package InsertTest; /* * 单客户端:批量插入 */ import java.sql.Connection; import java.sql.DriverManager; imp ...

  10. c# 十进制转二、八、十六进制

    一.十进制转二.八.十.十六进制字符串 Convert.ToString(int decNum,int toBase); decNum为十进制字符串, toBase可以为2.8.10.16 如果要转换 ...