随着云计算技术的不断发展,Serverless 架构越来越受到关注。Serverless 技术可以让开发人员更专注于业务逻辑,让基础设施运维屏蔽在云服务商的平台上,从而可以更快地构建出可靠、高效、弹性的应用程序,实现低成本、高扩展性的应用开发。
在 Serverless 编程中,一些操作需要进行多次,但每次操作的结果都应该是相同的。幂等性是这类操作中必不可少的概念。
幂等性的概念
在计算机科学中,幂等操作是指一个操作被执行一次或多次,结果都是一样的。如果一个操作不是幂等性的,那么当这个操作被执行多次时,每次的结果都可能不同。在复杂的分布式环境中,幂等性保证了操作的可重复性和正确性。
在 Serverless 中,一些操作例如数据写入、消息发布等都需要保证幂等性,否则会导致数据多次插入或者消息多次发送等问题。因此,开发人员需要对这些操作进行幂等设计。
幂等性的实现方式
1. 去重
当请求到达服务器时,首先需要进行去重操作,判断请求是否已经被处理过。如果请求已经被处理过,服务器就可以直接返回结果,否则继续处理请求。例如,在服务端使用 Redis 等缓存技术来实现去重,当请求到达时,将其参数作为键,查询缓存中是否有对应的值,如果有,就代表请求已经被处理过,可以直接返回缓存的结果。
示例代码:
// javascriptcn.com 代码示例 const redis = require('redis'); const client = redis.createClient(); function handler(event, context, callback) { const key = `${event.path}/${event.httpMethod}`; client.get(key, (err, result) => { if (result !== null) { console.log('request has been processed:', result); return callback(null, {statusCode: 200, body: JSON.stringify(result)}); } else { const data = process(event); client.set(key, data, 'EX', 300, (err) => { if (err) throw err; console.log('request has been processed:', data); return callback(null, {statusCode: 200, body: JSON.stringify(data)}); }); } }); } function process(event) { // handle request... return {code: 200, message: 'success'}; }
在上述代码中,通过 Redis 实现了请求去重的功能。
2. 处理并发
在分布式环境中,处理并发请求也是保证幂等性的重要手段之一。当多个请求同时到达服务器时,需要避免多个请求同时对同一个资源进行修改。此时可以使用分布式锁来避免并发修改。
示例代码:
// javascriptcn.com 代码示例 const redis = require('redis'); const client = redis.createClient(); function handler(event, context, callback) { const key = `${event.path}/${event.httpMethod}`; client.multi() .get(key) .incr(key) .exec((err, results) => { if (results[0] !== null) { console.log('request has been processed:', results[0]); return callback(null, {statusCode: 200, body: JSON.stringify(results[0])}); } else { const data = process(event); client.set(key, data, 'EX', 300, (err) => { if (err) throw err; console.log('request has been processed:', data); return callback(null, {statusCode: 200, body: JSON.stringify(data)}); }); } }); } function process(event) { // handle request... return {code: 200, message: 'success'}; }
在上述代码中,通过 Redis 实现了分布式锁的功能,保证了同一时刻只有一个请求可以进行修改操作。
3. 记录状态
对于一些需要多次执行的操作,例如多次发送消息或者多次对相同数据进行操作等,可以通过记录状态的方式来保证幂等性。例如,在服务端可以记录消息发送的状态,当重复发送相同的消息时,服务端可以返回之前的状态,避免重复发送。
示例代码:
// javascriptcn.com 代码示例 const redis = require('redis'); const client = redis.createClient(); function handler(event, context, callback) { const key = `${event.path}/${event.httpMethod}`; client.get(key, (err, result) => { if (result !== null) { console.log('request has been processed:', result); return callback(null, {statusCode: 200, body: JSON.stringify(result)}); } else { const data = process(event); client.setnx(key, JSON.stringify(data), (err, reply) => { if (err) throw err; if (reply === 1) { console.log('request has been processed:', data); return callback(null, {statusCode: 200, body: JSON.stringify(data)}); } else { client.get(key, (err, result) => { console.log('request has been processed:', result); return callback(null, {statusCode: 200, body: JSON.stringify(result)}); }); } }); } }); } function process(event) { // handle request... return {code: 200, message: 'success'}; }
在上述代码中,通过 Redis 实现了记录状态的功能,保证了多次发送消息时只会发送一次,并返回之前的状态。
总结
在 Serverless 编程中,幂等性是保证系统正确性的重要手段。开发人员需要对需要幂等性的操作进行设计,以确保系统的可靠性和正确性。通过去重、处理并发、记录状态等方式可以实现幂等性,在实践中需要根据实际情况选择适合的方案。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/653f01ff7d4982a6eb875673