原子性转账操作实现
import pymongo
from pymongo import MongoClient
from pymongo.write_concern import WriteConcern
from pymongo.read_concern import ReadConcern
from pymongo.read_preferences import ReadPreference
def transfer_money(from_account_id, to_account_id, amount):
client = MongoClient()
db = client['bank_db']
accounts = db['accounts']
transactions = db['transactions']
with client.start_session() as session:
session.start_transaction()
try:
# 检查转出账户余额是否足够
from_account = accounts.find_one({'account_id': from_account_id}, session=session)
if from_account['balance'] < amount:
session.abort_transaction()
return False
# 扣除转出账户金额
accounts.update_one(
{'account_id': from_account_id},
{'$inc': {'balance': -amount}},
session=session
)
# 增加转入账户金额
accounts.update_one(
{'account_id': to_account_id},
{'$inc': {'balance': amount}},
session=session
)
# 记录交易
transactions.insert_one(
{
'from_account': from_account_id,
'to_account': to_account_id,
'amount': amount,
'timestamp': '2023 - 10 - 01 12:00:00'
},
session=session
)
session.commit_transaction()
return True
except Exception as e:
session.abort_transaction()
return False
高并发转账场景性能优化方案
- 索引优化:
- 原理:在
accounts
集合的account_id
字段和transactions
集合的from_account
、to_account
字段上创建索引。这样在高并发场景下,查询账户信息和插入交易记录时,数据库能够更快地定位到相应文档,减少查询时间,从而提高系统性能。例如,accounts.create_index('account_id')
、transactions.create_index('from_account')
和transactions.create_index('to_account')
。
- 读写分离:
- 原理:使用MongoDB的副本集功能,将读操作分配到副本节点上,主节点只负责写操作。在高并发转账场景下,大量的账户余额查询(读操作)可以分担到副本节点,减轻主节点压力,提高系统整体的并发处理能力。通过设置
ReadPreference.SECONDARY_PREFERRED
可以优先从副本节点读取数据。
- 批量操作:
- 原理:将多个转账操作合并成一个批量操作。例如,如果有多个用户同时进行转账,可以将这些转账操作的更新和插入语句合并,一次性发送到数据库执行,减少数据库的交互次数,从而提高性能。在Python中,可以利用
pymongo
的批量操作方法,如update_many
和insert_many
。
- 缓存机制:
- 原理:在应用层引入缓存,如Redis。在处理转账请求时,先从缓存中读取账户余额信息,如果缓存中没有则从数据库读取,并将读取到的信息写入缓存。在更新账户余额时,同时更新缓存。这样在高并发场景下,大部分读操作可以直接从缓存获取数据,减少对数据库的压力,提高响应速度。