异质数据系统(heterogeneous data system)的数据同步是工作中经常会面临的问题,如:DBMS,Cache..双写模块,对于两个非原子性的操作要做到数据的最终一致性。通常采用方式:
1、采用Cache-Aside可能是项目中最常见的一种模式,应用程序同时和缓存以及数据库打交道,读数据时,应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中;写数据时,第一种策略更新数据库再更新缓存,第二种策略更新数据库再删除缓存。
2、采用Read-Through/Write-Through应用程序将缓存作为主要的数据源,而数据库对于应用程序是透明的,更新数据库和从数据库的读取的任务都交给缓存来代理。
3、采用Write-Back将缓存作为可靠的数据源,每次都只写入缓存,而写入数据库则采用异步的方式。
4、采用Write-Around和Write-Through不同,更新的时候只写入数据库,不写入缓存,结合Read-Through或者Cache-Aside使用,只在缓存未命中的情况下写缓存。
1、Cache-Aside在高并发时会导致数据不一致,有多个更新请求时,难以保证后更新数据库的请求会后更新缓存,例如,线程1读数据,由于未命中那么从数据库中取数据,线程2写数据库,线程2删除缓存,线程1由于网络延迟比较慢,将脏数据写入缓存。
2、Read-Through/Write-Through、Write-Back、Write-Around强依赖缓存数据源,有数据丢失的风险,如果缓存挂掉而数据没有及时写到数据库中,那么缓存中的有些数据将永久的丢失了。
1、通过CDC(Change Data Capture)获取变更数据源,CDC的核心思想是变更数据的捕获,获取数据库变化的数据集,引入mq组件延时消费变化的数据,在高并发的情况下,延迟消费mq可以确保之前缓存的脏数据被更新,缓存和数据库的数据最终一致性。
2、应用系统去除强依赖缓存组件,当缓存不可用或缓存数据为空时,直接同步加载数据库数据返回。
本方案是针对高并发的情况下修改数据保证数据的一致性。结合了Cache Aside+CDC+mq+版本号+延时+持久化的方式。
具体实现方案如下:
读数据时采用Cache Aside方式,应用程序先从缓存中查询是否有效数据,如果得到的话,直接返回,如果没有得到需要查询数据,查询成功后再同步保存到缓存中,以便下次查询不需要耗时查询数据库直接查询缓存返回结果。
修改数据数据时:
当收到修改数据的请求时,处理业务逻辑后先更新持久层的数据,这里持久层采用关系型数据库(oracle,mysql,sql server…)。利用关系型数据库的特性CDC(Change Data Capture),CDC能够帮助识别从上次提取之后发生变化的数据。利用CDC,在对源表进行INSERT、UPDATE或DELETE等操作的同时就可以提取数据,并且变化的数据被保存在数据库的变化表中。这样就可以捕获发生变化的数据,然后利用数据库视图以一种可控的方式提供给目标系统。这里结合笔者的经验修改数据事务提交后记录修改的数据集为binlog日志。CDC体系结构基于发布者/订阅者模型。发布者捕捉变化数据并提供给订阅者。订阅者使用从发布者那里获得的变化数据。通常,CDC系统拥有一个发布者和多个订阅者。发布者首先需要识别捕获变化数据所需的源表。然后,它捕捉变化的数据并将其保存在特别创建的变化表中。它还使订阅者能够控制对变化数据的访问。订阅者需要清楚自己感兴趣的是哪些变化数据。这里各更新缓存的应用服务器作为单独的消费者订阅变更的数据集。不过不会立即消费变化的数据,这是因为如果立即消费在高并发的情况下,缓存中设置了脏数据,例如上文的例子:线程1由于网络延迟比较慢,将脏数据写入缓存中,这时延时时间间隔消费确保脏数据写入缓存后可以对缓存数据进行更正,最终的数据一致性。需要数据库的每个表都有版本version字段,该字段来保证消费数据变化的是顺序性的,例如,现在库里version=1,缓存的数据版本也是version=1,数据修改2次后依次变为version=2和version=3,当先消费到version=3需要更新缓存时,发现缓存的version加1不等于消息体中的version,那么就会重试该消息体,直到消费了version=2的数据变化才更新缓存数据,这样保证了数据的正确性。
数据发生变化并不是直接更新缓存或置缓存无效,而是通过CDC捕获变更数据源更新,本方案采用关系型数据库库的特性binlog日志来作为数据源,binlog会记录修改的数据日志。使用延时间隔来消费数据库源,这样可以保证在高并发请求修改数据时的最终一致性和正确性。
任何技术方案都是在一定的场景下适用的,本方案适用的场景是高并发查询异样缓存,不直接查询库。
方案涉及结合Cache Aside+CDC+mq+延时+版本号+持久化的方式在高并发情况保证缓存和数据库数据一致性的解决方法。
(1) 在高并发请求修改数据的情况下,保证了数据的一致性。
(2) 高并发情况下更新缓存采用了异步解耦的方式,使各个组件各司其职,提高了接口的吞吐量,降低了响应时间。