之前的讲解,主要是在讲解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. mybatis调用存储过程的两种方式

    先总结和说明一下注意点: 1.如果传入的某个参数可能为空,必须指定jdbcType 2.当传入map作为参数时,必须指定JavaType 3.如果做动态查询(参数为表名,sql关键词),可以使用${} ...

  2. 提高Bash使用效率的方法

    环境:centos6.5 1.移动 Ctrl + a :移到命令行首Ctrl + e :移到命令行尾 Ctrl + xx:在命令行首和光标之间移动 左右键移动字符 Ctrl+左右键移动单词(不记快捷键 ...

  3. 设计模式之单例模式-C++

    单例模式也称单子模式.单件模式,通过单例模式可以保证系统中只有一个类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享 对于系统中的某些类来说,只有一个实例很重要,比如一个打印机可以 ...

  4. python3爆力破解rtsp脚本

    一.说明 hydra是说已实现了rtsp的爆力破解,但是使用时发现字典中明明已包含正确的用户名密码hydra却还没检测出来: 拦截数据包查看,感觉hydra只是尝试去匿名访问,并没有发送用户名密码去验 ...

  5. 使用Redis数据库(2)(三十四)

    除了String类型,实战中我们还经常会在Redis中存储对象,这时候我们就会想是否可以使用类似RedisTemplate<String, User>来初始化并进行操作.但是Spring ...

  6. a标签在编辑器中可以整体删除并且a标签为不可编辑的情况下 标签依然存在(棒棒哒)

    a标签在编辑器中可以整体删除并且a标签为不可编辑的情况下 标签依然存在 因为给a标签的后面 添加了一个空元素,如<i></i>(棒棒哒)<div contentEdita ...

  7. Linux下使用timedatectl命令时间时区操作详解

    timedatectl命令对于RHEL / CentOS 7和基于Fedora 21+的分布式系统来说,是一个新工具,它作为systemd系统和服务管理器的一部分,代替旧的传统的用在基于Linux分布 ...

  8. learning ddr mode reigster set command cycle time tMRD and tMOD

    tMRD: tMOD:

  9. 尚学堂java答案解析 第一章

    本答案为本人个人编辑,仅供参考,如果读者发现,请私信本人或在下方评论,提醒本人修改 一.选择题: 1.C 解析:java为了安全,中并没有引入C语言的指针概念. 2.AD 解析:B:Java先通过ja ...

  10. Java 实现倒计时(由秒计算天、小时、分钟、秒)

    public class Countdown4 { private static long day = 0; private static long hour = 0; private static ...