️测试问我:为啥阅读量计数这么简单的功能你都能写出bug?

2024-05-08 00:28

本文主要是介绍️测试问我:为啥阅读量计数这么简单的功能你都能写出bug?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

可乐他们团队最近在做一个文章社区平台,由于人手不够,后端部分也是由前端同学来实现,使用的是 nest

今天他接到了一个需求,就是在用户点开文章详情的时候,把阅读量 +1 ,这里不需要判断用户是否阅读过,无脑 +1 就行。

它心想:这么简单,这不是跟 1+1 一样么。

往期文章

仓库地址

  • 切图仔做全栈:React&Nest.js 社区平台(一)——基础架构与邮箱注册、JWT 登录实现
  • 切图仔做全栈:React&Nest.js社区平台(二)——👋手把手实现优雅的鉴权机制
  • React&Nest.js全栈社区平台(三)——🐘对象存储是什么?为什么要用它?
  • React&Nest.js社区平台(四)——✏️文章发布与管理实战
  • React&Nest.js全栈社区平台(五)——👋封装通用分页Service实现文章流与详情
  • 领导问我:为什么一个点赞功能你做了五天?

初版实现

我们用的 orm 框架是 typeorm ,然后他看了一眼官方文档,下面是一个更新的例子。

image.png

文章表里有一个字段 views ,表示该文章的阅读量。那我是不是把这篇文章的 views 取出来,然后 +1 ,再塞回去就可以了呢?

啪一下,就写出了下面这样的代码:

  async addView(articleId: number) {const entity = await this.articleRepository.findOne({where: { id: articleId },select: ['views', 'id'],});entity.views = entity.views + 1;await this.articleRepository.save(entity);}

然后就美滋滋的提测,继续摸鱼去了。

并发bug

不出意外的话意外就要发生了,测试下午就找到了可乐,说这个实现有 bug ,具体复现是在并发压测的时候。

这里用一个 node 脚本来模拟一下并发的请求:

import axios from "axios";const axiosInstance = axios.create({withCredentials: true,headers: {Cookie: "your cookie",},
});for (let i = 0; i < 10; i++) {axiosInstance.get("http://localhost:3000/api/articles/getArticleInfo?id=2");
}

本来应该阅读量加 10 的,结果只加了 1

image.png

可乐当时脑瓜子嗡嗡的,这还能有 bug

具体来说,这是 mysql 处理并发的机制—— MVCC ,它有几种默认的隔离级别。默认的隔离级别是可重复读,在可重复读的隔离级别下,会出现以下这种情况:

image.png

也就是说,当多个客户端同时读取相同的文章实体,然后分别对其浏览次数进行增加,并尝试保存回数据库,这有可能前面的提交会被后提交的操作覆盖,导致阅读量的的更新丢失。

update…set

最简单的解决方案就是不要取出来再更新,而是使用 mysqlupdate...set 语句,它本身自带的锁可以帮我们规避掉这种问题。

await this.articleRepository.query('UPDATE articles SET views = views + 1 WHERE id = ?',[articleId],
);

这一次再用测试脚本去跑的时候,发现是没有问题的了,加的次数是对的。

这篇关于️测试问我:为啥阅读量计数这么简单的功能你都能写出bug?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/968811

相关文章

一份LLM资源清单围观技术大佬的日常;手把手教你在美国搭建「百万卡」AI数据中心;为啥大模型做不好简单的数学计算? | ShowMeAI日报

👀日报&周刊合集 | 🎡ShowMeAI官网 | 🧡 点赞关注评论拜托啦! 1. 为啥大模型做不好简单的数学计算?从大模型高考数学成绩不及格说起 司南评测体系 OpenCompass 选取 7 个大模型 (6 个开源模型+ GPT-4o),组织参与了 2024 年高考「新课标I卷」的语文、数学、英语考试,然后由经验丰富的判卷老师评判得分。 结果如上图所

android 免费短信验证功能

没有太复杂的使用的话,功能实现比较简单粗暴。 在www.mob.com网站中可以申请使用免费短信验证功能。 步骤: 1.注册登录。 2.选择“短信验证码SDK” 3.下载对应的sdk包,我这是选studio的。 4.从头像那进入后台并创建短信验证应用,获取到key跟secret 5.根据技术文档操作(initSDK方法写在setContentView上面) 6.关键:在有用到的Mo

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现

Android我的二维码扫描功能发展史(完整)

最近在研究下二维码扫描功能,跟据从网上查阅的资料到自己勉强已实现扫描功能来一一介绍我的二维码扫描功能实现的发展历程: 首页通过网络搜索发现做android二维码扫描功能看去都是基于google的ZXing项目开发。 2、搜索怎么使用ZXing实现自己的二维码扫描:从网上下载ZXing-2.2.zip以及core-2.2-source.jar文件,分别解压两个文件。然后把.jar解压出来的整个c

回调的简单理解

之前一直不太明白回调的用法,现在简单的理解下 就按这张slidingmenu来说,主界面为Activity界面,而旁边的菜单为fragment界面。1.现在通过主界面的slidingmenu按钮来点开旁边的菜单功能并且选中”区县“选项(到这里就可以理解为A类调用B类里面的c方法)。2.通过触发“区县”的选项使得主界面跳转到“区县”相关的新闻列表界面中(到这里就可以理解为B类调用A类中的d方法

自制的浏览器主页,可以是最简单的桌面应用,可以把它当成备忘录桌面应用

自制的浏览器主页,可以是最简单的桌面应用,可以把它当成备忘录桌面应用。如果你看不懂,请留言。 完整代码: <!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><ti

python实现最简单循环神经网络(RNNs)

Recurrent Neural Networks(RNNs) 的模型: 上图中红色部分是输入向量。文本、单词、数据都是输入,在网络里都以向量的形式进行表示。 绿色部分是隐藏向量。是加工处理过程。 蓝色部分是输出向量。 python代码表示如下: rnn = RNN()y = rnn.step(x) # x为输入向量,y为输出向量 RNNs神经网络由神经元组成, python

LeetCode--204 计数质数

题目 统计所有小于非负整数 n 的质数的数量。 示例 示例:输入: 10输出: 4解释: 小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。 class Solution {public:int countPrimes(int n) {if (n <= 2) return 0;int cnt = 0;vector<bool> isPrime(n, true);

将一维机械振动信号构造为训练集和测试集(Python)

从如下链接中下载轴承数据集。 https://www.sciencedirect.com/science/article/pii/S2352340918314124 import numpy as npimport scipy.io as sioimport matplotlib.pyplot as pltimport statistics as statsimport pandas

开启青龙 Ninja 扫码功能失效后修改成手动填写CK功能【修正Ninja拉库地址】

国内:进入容器docker exec -it qinglong bash #获取ninjagit clone -b main https://ghproxy.com/https://github.com/wjx0428/ninja.git /ql/ninja#安装cd /ql/ninja/backend && pnpm install cp .env.example .env