脏数据

脏数据和时间戳,还有数据一致性校验

笑着哭i 提交于 2019-12-04 02:21:48
今天在开发补货管理模块时,要新增加一个接口,功能是可以修改补货管理表里的订单状态。 在数据库里,由一个orderStatus字段来表示订单的当前状态,而这个状态可以由两种用户角色进行修改。一个是加工厂,另一个是供应商。之前在写方法的时候,还没体会到数据一致性的问题。但是昨天由老欧写了一个接口给我看了之后,发现比我写的方法多用到了表里的lastModifiedOn和modifiedBy字段。来校验数据。心里有些疑惑,就让他给我讲讲这方面的东西。 他说:A在修改状态的时候,从前端获取到的状态是1,要将其修改成3.但是在这个过程中,B用户已经把状态修改成2了,那么,A获取到的状态1,就成为脏数据。: 脏数据在临时更新(脏读)中产生。事务A更新了某个数据项X,但是由于某种原因,事务A出现了问题,于是要把A回滚。但是在回滚之前,另一个事务B读取了数据项X的值(A更新后),A回滚了事务,数据项恢复了原值。事务B读取的就是数据项X的就是一个“临时”的值,就是脏数据。 在项目里:整个业务流程由spo.tpl spo.controller.php spo.SCA.php spo.model.php 组成。 tpl显示数据,controller组织数据,SCA发布接口,model实现接口。A用户在修改tpl上显示的数据的时候,一起取到了<input type="hidden" value="{

java--volatile关键字

此生再无相见时 提交于 2019-12-03 13:10:51
转:https://www.cnblogs.com/selene/p/5972882.html volatile不能保证数据同步 volatile关键字比较少用,原因无外乎两点,一是在Java1.5之前该关键字在不同的操作系统上有不同的表现,所带来的问题就是移植性较差;而且比较难设计,而且误用较多,这也导致它的"名誉" 受损。   我们知道,每个线程都运行在栈内存中,每个线程都有自己的工作内存(Working Memory,比如寄存器Register、高速缓冲存储器Cache等),线程的计算一般是通过工作内存进行交互的,其示意图如下图所示:      从示意图上我们可以看到,线程在初始化时从主内存中加载所需的变量值到工作内存中,然后在线程运行时,如果是读取,则直接从工作内存中读取,若是写入则先写到工作内存中,之后刷新到主内存中,这是JVM的一个简答的内存模型,但是这样的结构在多线程的情况下有可能会出现问题,比如:A线程修改变量的值,也刷新到了主内存,但B、C线程在此时间内读取的还是本线程的工作内存,也就是说它们读取的不是最"新鲜"的值,此时就出现了不同线程持有的公共资源不同步的情况。   对于此类问题有很多解决办法,比如使用synchronized同步代码块,或者使用Lock锁来解决该问题,不过,Java可以使用volatile更简单地解决此类问题

【转】分布式之数据库和缓存双写一致性方案解析

给你一囗甜甜゛ 提交于 2019-12-03 09:19:54
转自: https://www.cnblogs.com/rjzheng/p/9041659.html 引言 为什么写这篇文章? 首先,缓存由于其高并发和高性能的特性,已经在项目中被广泛使用。在读取缓存方面,大家没啥疑问,都是按照下图的流程来进行业务操作。 但是在更新缓存方面,对于更新完数据库,是更新缓存呢,还是删除缓存。又或者是先删除缓存,再更新数据库,其实大家存在很大的争议。目前没有一篇全面的博客,对这几种方案进行解析。于是博主战战兢兢,顶着被大家喷的风险,写了这篇文章。 文章结构 本文由以下三个部分组成 1、讲解缓存更新策略 2、对每种策略进行缺点分析 3、针对缺点给出改进方案 正文 先做一个说明,从理论上来说,给缓存设置过期时间,是保证最终一致性的解决方案。这种方案下,我们可以对存入缓存的数据设置过期时间,所有的写操作以数据库为准,对缓存操作只是尽最大努力即可。也就是说如果数据库写成功,缓存更新失败,那么只要到达过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存。因此,接下来讨论的思路不依赖于给缓存设置过期时间这个方案。 在这里,我们讨论 三种 更新策略: 先更新数据库,再更新缓存 先删除缓存,再更新数据库 先更新数据库,再删除缓存 应该没人问我,为什么没有先更新缓存,再更新数据库这种策略。 (1)先更新数据库,再更新缓存 这套方案,大家是普遍反对的。为什么呢

缓存和数据一致性问题

限于喜欢 提交于 2019-12-03 05:34:20
数据库和缓存双写一致性问题 在现在的架构中,缓存由于其高并发和高性能的特性,已经被广泛使用。在读取缓存方面,道理都很简单,但是在更新缓存这点上,到底是先更新缓存还是先更新数据库,存在着争议。 从理论上来说,给缓存设置过期时间,是保证最终一致性的解决方案。这种方案下,我们可以对存入缓存的数据设置过期时间,所有的写操作以数据库为准,对缓存操作只是尽最大努力即可。也就是说如果数据库写成功,缓存更新失败,那么只要到达过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存。因此,接下来讨论的思路不依赖于给缓存设置过期时间这个方案 三种更新策略 先更新数据库,再更新缓存 先删除缓存,再更新数据库 先更新数据库,再删除缓存 1. 先更新数据库,再更新缓存 这套方案,大家是普遍反对的。为什么呢?有如下两点原因。 原因一(线程安全角度) 同时有请求A和请求B进行更新操作,那么会出现 (1)线程A更新了数据库 (2)线程B更新了数据库 (3)线程B更新了缓存 (4)线程A更新了缓存 这就出现请求A更新缓存应该比请求B更新缓存早才对,但是因为网络等原因,B却比A更早更新了缓存。这就导致了脏数据,因此不考虑。 原因二(业务场景角度) 有如下两点: (1)如果你是一个写数据库场景比较多,而读数据场景比较少的业务需求,采用这种方案就会导致,数据压根还没读到,缓存就被频繁的更新,浪费性能。 (2

Redis缓存如何保证一致性

匿名 (未验证) 提交于 2019-12-03 00:43:02
为什么使用Redis做缓存 MySQL缺点 单机连接数目有限 对数据进行写速度慢 Redis优点 内存操作数据速度快 IO复用,速度快 单线程模型,避免线程切换带来的开销,速度快 一致性问题   读数据的时候首先去Redis里读,没有读到再去MySQL里读,读回来之后更新到Redis里作为下一次的缓存。写数据的时候回产生数据不一致的问题,无论是先写到Redis里再写MySQL还是先写MySQL再写Redis,这两步写操作不能保证原子性,所以会出现Redis和MySQL里的数据不一致。无论采取何种方式都不能保证强一致性,如果对Redis里的数据设置了过期时间能够保证最终一致性,对架构做的优化只能降低不一致性发生的概率,不能从根本上避免不一致性。   根据写入的顺序不同分为四种。 先删缓存,再更新数据库   这种操作的问题?   一般考虑某种策略的问题都是考虑该种策略会不会导致被删除的脏数据由于时序混乱再次被读线程从MySQL中读出来。A线程写数据,B线程读数据,A线程删除了缓存,B线程读数据发现缓存没有命中从数据库中读数据,B线程把读出的旧数据写到Redis里,A线程把新数据写回去。和下面的先写数据库再删缓存相比,这种方式显著的缺点 先删缓存,所以当两个线程并发的时候很大几率会出现缓存不命中,一旦缓存不命中,在写线程修改MySQL完成之前读进来的永远是脏数据

如何清除工作流脏数据

匿名 (未验证) 提交于 2019-12-02 23:56:01
问题: 工作流待我审批出现条数但是没有数据 解决方案: 去流程监控里面找到清理脏数据按钮即可 加入JEPaaS技术交流群,了解更多 转载请标明出处: 如何清除工作流脏数据 来源:51CTO 作者: JEPaaS云平台 链接:https://blog.51cto.com/13797782/2433522

【转载】缓存与数据库双写一致性问题

这一生的挚爱 提交于 2019-12-02 17:50:51
原文: https://learnku.com/articles/25012 前言 周所周知,在项目性能优化、提升的时候,我们引进了一个缓存的概念,即一款缓存数据的技术,项目在最初期架构规划时都会引进的一个组件。使用缓存有很多好处:加快请求的响应速度、减少数据库的交互与浪费大量的 IO 操作等,但是在某些场景下使用缓存也有可能会造成雪崩、穿透、数据不一致等问题,我们研究下使用缓存会导致有哪些数据不一致的情况发生以及在哪些场景会使用哪些具体的解决方案,首先我们必然还是会使用缓存的。 缓存更新策略 先更新数据库再更新缓存 浪费资源 每次去更新数据库再更新缓存都是需要申请 CPU 进行数据库的修改的,同时倘若数据的修改比较频繁以及数据的读操作却又比较少的时候,这种策略会导致出现冷数据的情况。 数据脏读 如果两个操作同时对数据进行操作时,举个栗子:线程 A 在线程 B 更新数据库成功后、更新缓存成功之前读取到数据,也就是读取到了缓存的旧数据。 该策略比较适合更新的频次比较少的场景下,比如博客的文章、基础数据、个人信息等场景。 先更新数据库再删除缓存 数据脏读 一个请求处理中过程中,倘若数据库更新成功了但是缓存更新失败了,那么后面的请求读取的数据都是旧数据、则脏数据。可以通过缓存过期时间定义缓存的有效期 (推荐),或者使用消息队列在删除缓存失败的时候再次异步更新缓存,直到成功为止

脏读(脏数据、脏页)、不可重复读、幻读

ぐ巨炮叔叔 提交于 2019-12-01 15:26:49
一、脏读(读到未提交的数据) 在理解脏读之前,需要理解脏数据的概念。 脏数据是指事务对缓冲池中行记录的修改,并且还没有提交。 注意脏数据和脏页是完全不同的两种概念, 脏页 指的是在缓冲池中已经被修改的页,但是还没有刷新到磁盘中,即数据库实例内存中的页和磁盘中的页的数据不一致。脏页的读取是非常正常的,脏页是数据库实例内存和磁盘异步造成的,这并不影响数据的一致性,脏页最终会被刷新到磁盘中。 脏读指的是在不同事务下,当前事务可以读取到另外事务未提交的数据,简单来说就是可以读到脏数据。 和脏页不同,如果读到了脏数据,即一个事务读取到了另外一个事务未提交的事务,显然 违反了了事务的隔离性 。 下面举个例子 转账事务 取款事务 1 开始事务 2 开始事务 3 查新账户余额为2000 4 取款1000元,余额改为1000 5 查询账户余额为1000(脏读) 6 取款发生错误,事务回滚,余额变为2000 7 转入2000,余额变为3000(1000+2000) 8 提交事务 备注 正常逻辑此时账户为4000元 脏读现象在实际生产环境并不常见 ,因为脏读发生的条件是需要事务的隔离级别为READ UNCOMMITTED,而目前绝大多数数据库都至少设置成READ COMMITTED。InnoDB存储引擎默认事务隔离级别为READ REPEATABLE。 二、不可重复读(前后读取到的数据内容不一致)

游戏服务器和Web服务器的区别

帅比萌擦擦* 提交于 2019-12-01 09:55:57
用Go语言写游戏服务器也有一个多月了,也能够明显的感受到两者的区别。这篇文章就是想具体的聊聊其中的区别。当然,在了解区别之间,我们先简单的了解一下Go语言本身。 1. Go语言的特点 Go语言跟其他的语言例如Java比起来,算得上一门很年轻的语言。Go语言是由Robert Griesemer、Rob Pike和Ken Thompson于2007年在Google开发。并于2009年正式发布。 Go语言的设计理念围绕着简洁这两个字,认为少即是多。如果你熟悉Java,用Java那一套语法命名跟Go做对比,可以很明显的体会到这种感觉。 Go的特点可以简单的概括成以下几个点。 1.1 静态类型和编译型 首先Go是静态类型,静态类型就是编译时就知道每一个变量的类型,得益于此,在编译的阶段就能够发现很多问题。而如果是动态语言,例如JavaScript,有些问题直到运行时才能发现。 Go是编译型语言,看到编译型大家脑子里可能会想到另外一个词解释型。两者的区别从字面上来理解其实已经可以看出来,我用一个简单的例子来类比一下。 编译型 去餐馆吃饭,点了菜之后,饭店会等所有的菜做好了再上 解释型 去餐馆吃饭,点了菜之后,陆陆续续的边吃边上 1.2 跨平台 顾名思义,你写的Go源码在所有的系统都能够运行。 这点其实很好理解,例如Java的口号是"Write once, run anywhere"

Redis缓存和数据库一致性问题

放肆的年华 提交于 2019-11-30 00:06:41
工作中,经常会遇到缓存和数据库数据一致性问题。从理论上设置过期时间,是保证最终一致性的解决方案。这种方案下,我们可以对存入缓存的数据设置过期时间,所有的写操作以数据库为准,对缓存操作只是尽最大努力即可。也就是说如果数据库写成功,缓存更新失败,那么只要到达过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存。因此,接下来讨论的思路不依赖于给缓存设置过期时间这个方案。 在这里,我们讨论三种更新策略: 1) 先更新数据库,再更新缓存 2) 先删除缓存,再更新数据库 3) 先更新数据库,再删除缓存 (1) 先更新数据库,再更新缓存 这套方案,大家是普遍反对的。为什么呢?有如下两点原因。 原因一(线程安全角度) 同时有请求A和请求B进行更新操作,那么会出现 (1)线程A更新了数据库 (2)线程B更新了数据库 (3)线程B更新了缓存 (4)线程A更新了缓存 这就出现请求A更新缓存应该比请求B更新缓存早才对,但是因为网络等原因,B却比A更早更新了缓存。这就导致了脏数据,因此不考虑。 原因二(业务场景角度) 有如下两点: (1)如果你是一个写数据库场景比较多,而读数据场景比较少的业务需求,采用这种方案就会导致,数据压根还没读到,缓存就被频繁的更新,浪费性能。 (2)如果你写入数据库的值,并不是直接写入缓存的,而是要经过一系列复杂的计算再写入缓存。那么,每次写入数据库后