Skip to main content

One post tagged with "transation"

View All Tags

· One min read

问题背景

发现生产环境的业务报了好多错误, 涉及的 Node.js 代码是一个基于 Redis 的频率计数器,那部分逻辑大概是这样

// 查询并增加一次计数
async incr (id) {
const key = `${this.namespace}:${id}`
const now = getMicrotime()
const start = now - this.duration * 1000

const operations = [
['zremrangebyscore', key, 0, start],
['zcard', key],
['zadd', key, now, now],
['pexpire', key, this.duration]
]

const res = await this.redis.multi(operations).exec()
const count = toNumber(res[1][1])
return count
}

错误是:

Cannot read property '1' of undefined

· One min read

解决的思路主要还是使用原生的方式打开一个事务。

下面是在stackoverflow上的一个帖子的答案

http://stackoverflow.com/questions/25079408/how-to-handle-async-concurrent-requests-correctly/25100188#25100188

buyItem: function(req, res) {
try {
// Start the transaction
User.query("BEGIN", function(err) {
if (err) {throw new Error(err);}
// Find the user
User.findOne(req.param("userId").exec(function(err, user) {
if (err) {throw new Error(err);}
// Update the user balance
user.balance = user.balance - req.param("itemCost");
// Save the user
user.save(function(err) {
if (err) {throw new Error(err);}
// Commit the transaction
User.query("COMMIT", function(err) {
if (err) {throw new Error(err);}
// Display the updated user
res.json(user);
});
});
});
});
}
// If there are any problems, roll back the transaction
catch(e) {
User.query("ROLLBACK", function(err) {
// The rollback failed--Catastrophic error!
if (err) {return res.serverError(err);}
// Return the error that resulted in the rollback
return res.serverError(e);
});
}
}

不过提个建议就是,这种写法的风格不好,建议改成promise方式

还有个npm模块是在sails-mysql基础上封装了事务 https://github.com/postmanlabs/sails-mysql-transactions