【世界报资讯】一次全量数据对比工具发现问题的过程与思考
如果没有这次全量数据对比工具,那么也许这个历史问题会继续隐藏着,直到发生线上事故才暴露出来,毕竟人工抽样验证发现的概率只有「5.8%」
【资料图】
背景是发票系统有18500个电子发票订单被财务系统驳回了,驳回原因是财务系统上线了全电发票需求,上线后电子发票枚举被误删,无法处理电子发票。需要我们发票系统对这18500电子发票订单,重新触发提票,让发票能正常开出来。也就是,我们需要刷数。刷数是个高危操作,极易引发线上问题。
经验教训告诉我们,刷数虽然是一种处理线上问题的方法,但是也特别容易引起二次事故。对于刷数,我们需要像新需求一样对待,经过完备的需求分析、设计评审、代码评审。主要考虑以下3点:
刷数范围,怎么筛选问题数据,评审过滤条件;刷数程序,怎么修复问题数据,评审代码逻辑;验证方法,怎么验证修复数据,分析测试场景;在刷数实施前,群里报备,周知相关方及相关人员。先试刷,验证无问题后,再全刷,最后验证问题数据已经得以修复。这一套刷数流程,通过加强前期评审,能很好地预防缺陷,增强刷数成功的信心。但是人工评估可能遗漏场景,可能对真实数据情况把握不全,刷数的关键还在于最后的数据验证。
抽样验证还是全量验证,这是一个问题。抽样验证是人工随机挑几个数据进行验证,我们通常倾向于使用抽样验证,一是抽样验证是一种科学的有效的验证方法,虽然它存在一定概率的遗漏,但是很多时候是可以接受的风险;二是抽样验证也是无奈之举,找不到办法进行全量验证。我们遇到的困难是,数据存在ES中,批量把所有数据查出来很麻烦,也无法直接编写校验逻辑,全量验证似乎是不可能的。
全量验证有2个思路:
如果能直连库,那么先提数,再写程序对比;如果只能WEB页面查数,那么使用Python爬虫提数,再写程序对比;后者适用于我们的情况。ES能通过WEB页面查询数据,只要是WEB页面,即使有Cookie,也能爬取到接口数据。F12抓包到查询接口的URL、Cookie、入参后,使用Python的requests库可以爬取查询结果数据:
url = "http://xxx"headers = { "Cookie": "xxx", "Content-Type": "application/json"}response = request("get", url=url, headers=headers)result = response.json()
我们使用这种方式,传入订单号,查询到了申请单数据,以便进行对比校验逻辑。而订单号,研发打在了日志里,需要下载日志文件后,进行解析,可以使用Python切片:
orders = set()with open("some.log") as f: for line in f.read().splitlines(): if "xxx" in line: orders.add(line[line.index("orderId="):line.index(",已执行")].replace("orderId=", ""))print(len(orders))with open("orders.txt", "w") as f: f.writelines(",".join(orders))
.index可以定位到关键词的索引,然后[:]切片获取指定内容。
日志解析订单号+爬虫获取申请单+编写对比校验逻辑,全量数据对比工具就完成了。可是18500单,上万级别数据,要全部对比完,至少要几个小时。是时候使用多线程了。
多线程第一步,拆解数据,将18500单拆成以100单为一组的列表:
def split_list(lst, size): """ 将列表 lst 拆分成每份 size 个元素的子列表,并返回一个包含所有子列表的列表。 """ return [lst[i:i + size] for i in range(0, len(lst), size)]
多线程第二步,队列提数,让多个线程依次从列表中取出数据,每个线程每次取不同的数据:
import threading# 待处理的数据列表data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]# 创建锁对象lock = threading.Lock()# 定义线程函数def process_data(): global data while True: # 加锁 lock.acquire() # 如果列表为空,说明所有数据已被处理完毕,退出循环 if len(data) == 0: lock.release() break # 取出列表中的第一个数据 num = data.pop(0) # 释放锁 lock.release() # 对数据进行处理 print("Processing data:", num)# 创建多个线程threads = []for i in range(5): t = threading.Thread(target=process_data) threads.append(t)# 启动所有线程for t in threads: t.start()# 等待所有线程结束for t in threads: t.join()print("All data processed.")
阻塞队列是通过加锁来实现的,每个线程在取数前先加锁,然后pop(0)取出列表中的第一个数据,再释放锁。上述程序修改①data②数据处理逻辑③线程数即可使用。
对比工具使用多线程后,运行时间从小时级别降到了分钟级别。当天研发本来以为要跑很久,准备第二天再来看,就先撤了。我执着了一下多线程实现,在ChatGPT帮助下,很快就把结果跑出来。赶紧打电话摇人,让研发回来看问题,研发那时刚到家,掏出钥匙把门打开。在全量对比前,我们也都做了一轮抽样验证,均没有发现任何问题。18500单全量对比,发现有1064单存在问题,能抽样发现的概率只有5.8%。
总结,分析这些问题原因:
遗漏了1种数据情况,评估不到位未考虑到刷数环境影响,在预发环境刷数,上下游环境都是预发,可能跟线上版本不一样,尤其是做写操作时,格外需要注意刷数程序本身缺陷,这个缺陷隐藏在一段用了很多次刷数的历史代码里面,不是100%会导致问题可以发现,大数据量验证,人工无法百分百保证数据准确性,抽样检查,94.2%概率发现不了问题。最稳妥的办法,还是全量对比,让每条数据,都经过对比规则的检验。
关键词:
责任编辑:宋璟
-
【世界报资讯】一次全量数据对比工具发现问题的过程与思考
-
通讯!日本东京成田机场和羽田机场区别_日本东京的成田机场与羽田机场有什么不同吗 哪个离市区近 _360
-
流浪汉模拟器虫子帮基地在哪-当前通讯
-
中标利率继续不变 央行小额加量续作MLF 天天新消息
-
美亚柏科:公司推出的AIGC检测平台支持AIGC生成文本的检测识别
-
使用Python的无线通信
-
唯心主义主张物质是意识的产物(唯心主义主张意识第一性 物质第二性 认为意识世界本原 如何正确)
-
全球最大黄金ETF--SPDR Gold Trust持仓较上日减少3.47吨,当前持仓量为934.07吨_最新快讯
-
欧莱雅润发乳是洗发水还是护发素_润发乳是护发素|热讯
-
【天天快播报】姚明年中文版国语-姚明年中文版
-
世界热资讯!华菱精工: 宣城市华菱精工科技股份有限公司未来三年(2023年-2025年)股东分红回报规划
-
观天下!贵州民航集团:数字技术赋能民航业务链
-
证明姥姥不在世愁坏六旬老人,继承难题是否可以提供变通方案
-
天天速看:K W NELSON GP(08411)公布一季度业绩 净亏损98.3万港元 同比扩大约20%
-
热议:中国国航:4月旅客周转量同比上升630.5%
-
静安区谈家桥城市更新项目全面冲出“正负零” 完工后将建成集居住、购物、教育为一体的多元化社区中心-天天实时
-
惠普推出Pavilion Aero 13 2023笔记本:镁铝合金机身 轻至998.8g
-
邻居砸掉3面承重墙女子新房变危房 物业:哪买的房去哪退 世界新要闻
-
稳如“老司机”的智能驾驶是怎样的?我在问界M5上找到了答案
-
兴证宏观:生产改善分化
-
51699888会员管理平台(5169888会员平台登录)
-
影像看齐Ultra!小米14 Pro曝光:长焦镜头大升级
-
当前看点!女子怀孕后发现男友已婚 法院这么判
-
山西大同中考成绩2021录取分数线_山西大同中考成绩查询 快讯
-
重点聚焦!诸葛亮设下空城计,为何门口安排4名士兵扫地司马懿一看就懂了
-
爱立信学院
-
德意志银行顺利完成“北向互换通”下首笔交易-今日视点
-
好表到底戴左手还是右手?正确秀表,瞅瞅三要素 #表叔王寂 今日要闻
-
全球新资讯:狮子女和双鱼男是孽缘吗 狮子女会把双鱼男虐死
-
九方财富IPO上市,未来发展值得关注|焦点速讯
-
回流焊和波峰焊的区别(smt工艺中回流焊与波峰焊的区别)
-
新能源板块领涨,新能源50ETF(516270)涨3.38%,新能源车ETF华安(516660)涨3.34%,光伏ETF华安(159618)涨3.3%
-
誉衡药业:5月12日融券卖出1.08万股,融资融券余额2.33亿元|环球热消息
-
个体户都能领创业补贴?假的
-
天天速读:依法管理“网红青蛙”无可非议,但应多些柔性考量