脏读不可重复读幻读;qps、tps、并发量、pv、uv;接口幂等性问题如何解决
脏读不可重复读幻读
脏读
脏读指的是一个事务在读取了另一个事务未提交的数据后,后续操作中,另一个事务发生了回滚(Rollback),导致读取到的数据实际上是无效的。这就像读取了一份尚未确认是否有效的数据,如果最终该事务被回滚,那么读取到的数据就是脏数据。脏读会导致数据的不一致性和错误。
不可重复读
不可重复读指的是在一个事务内,对同一数据进行了两次读取,但在两次读取之间,另一个事务对该数据进行了修改并提交,导致两次读取的结果不一致。也就是说,某个事务在读取数据时,数据被其他事务修改了,从而产生了不一致的情况。update
幻读
幻读解决了不可重复读的问题了,幻读指的是在一个事务内select某记录是否存在,不存在准备插入此记录,但执行insert时发现此记录已存在,无法插入,此时发生了幻读。
总结
ru-存在脏读、不可重复读、幻读
rc-解决了脏读,存在不可重复读、幻读
rr-解决了脏读、不可重复读,存在幻读
se-全部解决,牺牲了效率
-- 设置隔离级别为READ UNCOMMITTED
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
mysql5.7以后默认隔离级别
MySQL 5.7之后的默认隔离级别是REPEATABLE READ(可重复读)
补充
oracle仅支持2种隔离级别:rc,se,默认rc,存在不可重复读和幻读问题
qps、tps、并发量、pv、uv
qps
QPS(Queries Per Second):每秒查询率,一台服务器每秒能够响应的查询次数,每秒的响应请求数。对于数据库来说,QPS是指每秒处理的SQL查询次数;对于应用程序来说,QPS是指每秒处理的请求次数。
# 如何估算自己项目的QPS?
使用日志估算即可,比如在中间件里记录访问日志,最终统计1s内有多少个访问,qps就是多大;
一个接口的qps跟业务流程有关,跟是否使用缓存有关
不使用缓存:大约8核16G机器,qps 400多,如果横向扩展,10台8核16g的机器,qps大约4000多
使用缓存:大约8核16G机器,qps破千没问题
tps
TPS(Transactions Per Second):每秒事务处理量,包括一条消息入河一条消息出,加上一次用户数据库访问。
-过程:客户端请求服务端、服务端内部处理、服务端返回客户端。
-例如,访问一个 Index 页面会请求服务器 3 次,包括一次 html,一次 css,一次 js,那么访问这一个页面就会产生一个T,产生三个Q
并发量
并发量(Concurrency):系统同时处理的请求或事务数,可以直接理解为:系统同时处理的请求数量
QPS = 并发量/平均响应时间
并发量 = QPS * 平均响应时间
例如当前系统QPS为1w,每个请求的响应时间都是2s,那么并发量就是2w
pv
PV(Page View):页面访问量,即页面浏览量或点击量,用户每次刷新即被计算一次。可以统计服务一天的访问日志得到。
uv
UV(Unique Visitor):独立访客,统计1天内访问某站点的用户数。可以统计服务一天的访问日志并根据用户的唯一标识去重得到。
DAU
DAU(Daily Active User):日活跃数量。常用于反应网络、app、网游的运营情况
DAU通常统计一日之内,登陆或使用了某个产品的用户数(除去重复登陆的用户)
MAU
MAU(Month Active User):月活跃用户数量,指网站、app等去重后的月活跃用户数量
接口幂等性
定义
-幂等:幂等(idempotent、idempotence)是一个数学与计算机学概念
-一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同
-接口幂等性:无论调用多少次,产生的效果是一样的
-get 获取数据天然幂等
-put 修改数据天然幂等
-修改库存(数字加减):不幂等
-delete 删除 天然幂等
-post 新增数据,会出现不幂等的情况,要把它做成幂等性的
解决方案
# token机制
1、下单接口的前一个接口,只要一访问,后端生成一个随机字符串,存到redis中,把随机字符串返回给前端
2、然后调用业务接口请求时,把随机字符串携带过去,一般放在请求头部。
3、服务器判断随机字符串是否存在redis中,存在表示第一次请求,然后redis删除随机字符串,继续执行业务。
4、如果判断随机字符串不存在redis中,就表示是重复操作,直接返回重复标记给client,这样就保证了业务代码,不被重复执行
# 乐观锁机制---》更新的场景中
update t_goods set count = count -1 , version = version + 1 where good_id=2 and version = 1
1、在数据表中添加一个用于版本号或时间戳的字段。这个字段用于记录资源的状态变化。
2、在前一个接口请求时,后端生成一个幂等性token,并将其存储到Redis中,以及将幂等性token与数据表中的版本号或时间戳一起返回给前端。
3、在业务接口请求时,前端通过请求头部(Header)或请求参数的方式将幂等性token和资源的版本号或时间戳一起发送到后端。
4、后端接收请求后,首先从Redis中查询幂等性token是否有效,如果有效,再根据资源的版本号或时间戳与请求中的版本号或时间戳进行比较,如果相等,说明该请求是幂等的,可以执行更新操作,并更新资源的版本号或时间戳,同时删除Redis中的幂等性token,确保该幂等性token只能使用一次。如果版本号或时间戳不匹配,说明该请求可能是重复提交的或者数据已经被其他请求修改,返回幂等性错误。
# 唯一主键
-这个机制是利用了数据库的主键唯一约束的特性,解决了在insert场景时幂等问题。但主键的要求不是自增的主键,这样就需要业务生成全局唯一的主键
-假设我们有一个订单表,我们可以将订单号作为唯一主键。当用户下单时,服务器端生成唯一的订单号,并将该订单号作为主键存储到数据库中。之后,无论用户如何重复提交下单请求,由于订单号是唯一的,数据库会阻止插入重复的订单记录。
-需要注意的是,虽然唯一主键可以保证在数据库层面避免重复插入数据,但对于前端或客户端来说,仍然需要处理网络错误和异常情况,例如网络超时或请求失败。这些异常情况可能导致用户多次提交相同的请求,而数据库唯一主键只能保证数据库中不会出现重复记录,但无法阻止客户端多次发起请求。因此,唯一主键只是幂等性的一部分,还需要结合其他机制,如幂等性token或乐观锁等,来全面保证接口的幂等性。
# 唯一ID(unique)
调用接口时,生成一个唯一id,redis将数据保存到集合中(去重),存在即处理过
# 防重表
使用订单号orderNo做为去重表的唯一索引,把唯一索引插入去重表,再进行业务操作,且他们在同一个事务中。这个保证了重复请求时,因为去重表有唯一约束,导致请求失败,避免了幂等问题。这里要注意的是,去重表和业务表应该在同一库中,这样就保证了在同一个事务,即使业务操作失败了,也会把去重表的数据回滚。这个很好的保证了数据一致性。
# 前端:
按钮只能点击一次
标签:pv,请求,读幻读,重复,uv,接口,脏读,qps,主键
From: https://www.cnblogs.com/10086upup/p/17596671.html