Redis与关系型数据库的同步问题
Redis是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key-value存储的不足,在部分场合可以对关系数据库起到很好的补充作用。它提供了Python,Ruby,Erlang,PHP客户端,使用很方便。
按照我们一般的使用Redis的场景应该是这样的:
也就是说:我们会先去Redis中判断数据是否存在,如果存在,则直接返回缓存好的数据。而如果不存在的话,就会去数据库中,读取数据,并把数据缓存到redis中。适用场合:如果数据量比较大,但不是经常更新的情况(比如用户排行)
而第二种Redis的使用,跟第一种的情况完成不同,具体的情况请看:
这里我们会先去Redis中判断数据是否存在,如果存在,则直接更新对应的数据(吧对应更新过的key记录下来,比如也保存到redis中,key为save_update_keys),并把更新后的数据返回给页面,而如果不保存的话,就会去先更新数据库中的内容,然后把数据保存一份到Redis。后面的工作,后台会有相关机制把Redis中的save_update_keys存储的key,分别读取出来,找到对应的数据,更新到DB中。优点:主要目的是把Redis当做数据库使用,更新获取数据比DB块,非常适合大数据量的频繁变动(比如微博),缺点,对Redis的依赖很大,要做好宕机时的数据保存。
Redis和数据库同步问题
缓存充当数据库
比如说Session这种访问非常频繁的数据,就适合采用这种方案;当然了,既然没有涉及到数据库,那么也就不会存在一致性问题;
缓存充当数据库热点缓存
读操作
目前的读操作有个固定的套路,如下:
客户端请求服务器的时候,发现如果服务器的缓存中存在,则直接取服务器的;
如果缓存中不存在,则去请求数据库,并且将数据库计算出来的数据回填给缓存;
返回数据给客户端;
写操作
各种情况会导致数据库和缓存出现不一致的情况,这就是缓存和数据库的双写一致性问题;
目前缓存存在三种策略,分别是
Cache Aside 更新策略:同时更新缓存和数据库;
Read/Write Through 更新策略:先更新缓存,缓存负责同步更新数据库;
Write Behind Caching 更新策略:先更新缓存,缓存定时异步更新数据库;
三种策略各有优缺点,可以根据业务场景使用;
Cache Aside 更新策略
该策略大概的流程就是请求过来时先从缓存中取,如果命中缓存的话,则直接返回读取的数据;相反如果没有命中的话,接着会从数据库中成功获取到数据后,再去清除缓存中的数据;具体流程图如下:
但是以上在某些特殊的情况下是存在问题:
问题1:先更新数据库,后更新缓存
两个线程在高并发的情况下就会可能出现数据脏读的情况:
线程A执行写操作,成功更新数据库;
线程B同样执行和线程A一样的操作,但是在线程A执行更新缓存的过程中,线程B更新了新的数据库数据到缓存中;
线程A在线程B全部操作完成以后才将相对老的数据又更新到了缓存中;
问题2:先删除缓存,后更新数据库
同样的,在高并发场景下同样会出现脏读的情况:
线程A成功删除了缓存,等待更新数据库;
线程B进行读操作,由于此时缓存已经被删除了,因此线程B重新从数据库中获取老的数据并且更新到了缓存中;
线程A在线程B完成了整个的读操作以后,才更新数据库,此时缓存中的数据依旧是老的数据;
问题3:先更新数据库,后删除缓存
目前这是比较普遍的操作,即使它还是有可能会出现脏读的情况:
线程A进行读操作,此时正好没有命中缓存,接着请求数据库;
线程B进行写操作,在线程A没有从数据库中获取到数据之前,把数据写入到数据库中,并且还成功删除了缓存;
线程A在线程B完成了整个的写操作以后,才将相对老的数据更新到缓存中;
但是以上的情况比较不会出现,这是因为上述情况需要满足线程A的读操作要慢于线程B的写操作,但是在现实过程中,读操作通常都是要快于写操作得多的,但是为了避免发生以上的情况,通常都是要给缓存加上一个过期的时间;
但是设想一下,如果上面的删除缓存失败了怎么办呢,这样显然会导致数据脏读的情况,我觉得方案如下:
设置缓存的过期时间(必须要做);
提供一个保障重试机制,将哪些删除失败的key提供给消息队列去消费;
从消息队列取出这些key再次进行删除,失败再次加入到消息队列中,超过一定次数以上则人工介入;
但是以上情况需要在业务代码中进行操作,显然得需要进行解耦;
目前我们公司就是使用该方案,具体过程为在更新数据库数据的时候,数据库会以binlog日志的形式保存下来,通过canal开源软件将binlog解析成程序语言可以解析的地步,接着订阅程序获取到这些数据以后,尝试删除缓存操作,如果操作失败的话,则将其加入到消息队列中,重复消费,当删除操作的失败次数到达一定的次数以后,还是得人工介入。
Read/Write Through 更新策略
该模式下,程序只需要维护缓存即可,数据库的同步工作交由缓存来同步更新;
该策略具体又分为两种:
Read Through:在查询的过程中更新缓存;
Write Through:在写操作的过程中如果命中缓存,则直接更新缓存,数据库则由缓存自己同步去更新;
Write Behind Caching 更新策略
该策略只更新缓存,不会立马更新数据库,只会在一定的时间异步的批量去操作数据库;这样的好处在于直接操作缓存,效率极高,并且操作数据是异步的,还可以将多次的操作数据库语句合并到一个事务中一起提交,因此效率很客观;
但是,该策略没有办法做到数据强一致性,并且实现逻辑相对是比较复杂的,因为它需要确认哪些是需要更新到数据库的,哪些是仅仅想要存储在缓存中的;
比较
目前通常使用的是第一种策略中的先更新数据库,后更新缓存;其他的相较比起来实现都比较复杂;
最后想说的是,缓存本来就是为了牺牲强一致性来提高性能的,所以肯定会存在一定的延迟时间,我们只需要保证最终的数据一致性即可;
Redis与关系型数据库的同步问题相关推荐
- Redis 非关系型数据库 安装以及相关命令
目录 一.缓存简介 1.1 系统缓存 1.2 缓存保存位置及分层结构 1.2.1 DNS缓存 1.2.2 应用层缓存 1.2.3 数据层缓存 分布式缓存服务 数据库 1.2.4 硬件缓存 二. 关系数 ...
- Redis非关系型数据库(三)持久化
目录 一.redis高可用 1.持久化 2.主从复制 3.哨兵 4.集群(cluster) 二.Redis的持久化 1.RDB持久化 2.AOF持久化(append only file) 3.RDB和 ...
- 五、redis和关系型数据库如何配合使用
1.先写缓存,在写数据库(这个需要考虑一下业务的合理性 ) 讲解:先写缓存,再写数据库.应用程序前端直接读写 Redis,后端匀速异步地把数据持久化到 MySQL 或 TiDB.这种做法一般被称之为& ...
- 关于Redis与关系型数据的一些区别
Redis能替代关系型数据库吗? 为什么? 不能替代, 两者侧重点不同, redis是非关系型数据库,以k-v形式存储的内存数据库. 1,基于数据存在于缓存中如果redis服务器出现宕机的情况,会造成 ...
- MySQL数据库是非关系_MySQL(数据库)基础知识、关系型数据库yu非关系型数据库、连接认证...
什么是数据库? 数据库(Database):存储数据的仓库 高效地存储和处理数据的介质(介质主要是两种:磁盘和内存) 数据库系统:DBS(Database System):是一种虚拟系统,将多种内容关 ...
- 非关系型数据库-NoSQL(Redis)
文章目录 一.什么是 NoSQL? 二.NoSQL 的特性? 三.什么是 Redis? 四.Redis 安装部署 4.1 下载安装包 4.2 编译安装 4.3 修改配置文件 4.4 启动服务 4.5 ...
- hbase redis mongoddb neo4j 非关系型数据库简介
Hbase 列式存储以流的方式在列中存储所有的数据.对于任何记录,索引都可以快速地获取列上的数据:列式存储支持行检索,但这需要从每个列获取匹配的列值,并重新组成行.HBase(Hadoop Datab ...
- mysql同步大师_数据库大师成长日记:您最需要了解的NoSQL非关系型数据库
朋友们,我们平时使用的数据库,大多都是关系型数据库,包括MySQL.PostgreSQL.SQLServer等.关系型数据库的特点是数据的存储通过二维表格实现,将数据存储在相互独立的表格中. 近年来, ...
- 关系型数据库(Relational Database)与非关系型数据库(NoSQL)的区别:(MySQL,Redis,Memcache,MongoDB)
Table of Contents 关系型数据库(Relational Database) 什么是关系数据库 什么是SQL? 关系数据库的结构 关系模型 关系数据库的好处 数据一致性 隔离性和原子性 ...
最新文章
- 配置中心Apollo的设计原理
- wps插件实用插件_6款实用PS插件合集,好用的PS插件都在这里!
- Go 语言编程 — 并发 — 同步原语与锁
- UA MATH574M 统计学习V Variable Selection: LASSO
- python中i+=1不等于++i
- Python_面向对象_zipfile和tarfile
- 乐乐勇智能教育机器人有多少型号_【头条】协作机器人平台化趋势将会是柔性自动化的破局之道...
- UVA - 213 Message Decoding
- Linux如何修改环境变量PATH,以及系统登录时读取文件的顺序
- jQuery动画之显示隐藏动画
- 2020最新版《神经网络与深度学习》中文版更新完毕,pdf开放下载
- 小程序 图片显示模式详解
- ps软件打不开计算机受限制,win10系统打不开ps软件的处理技巧
- 笔记本无线网口共享网络给以太网口
- XAMPP下的Tomcat 7运行出现“1% 不是有效的 Win32 应用程序。”
- 最新资讯:iPhone 11显示模块更换计划,用于解决触摸问题
- 用计算机四舍五入偷银行储户的钱,银行家舍入VS四舍五入(下):.NET发现之旅(四)...
- Java高并发编程 (马士兵老师视频)笔记(一)同步器
- 高山流水 (余秋雨)
- 微软出手,干翻 IDEA?网友:先干翻 Eclipse 吧
热门文章
- selenium无法定位到QQ邮箱登录页面的输入框元素和登录按钮元素-解决方法
- Xamarin Mono for VS开发窗体标题(Title)乱码解决方案
- 细数改善WPF应用程序性能的10大方法
- XML Schema ---complexType-----复合元素
- 简述用UCenter整合第三方应用程序
- sharepoint站点移植方案
- cognos10 安装部署
- 解不等式之代数和不等式
- 德国超级计算机中心,德国:强化人工智能能力建设 加大高性能计算网络投资...
- mysql日期格式化季度_mysql按年度、季度、月度、周、日统计查询的sql语句