在 MongoDB 上模拟事务操作来实现支付
我们的产品叫「学海密探」,属于在线教育行业,产品需要有支付功能,然而支付最蛋疼是什么?有人会说是支付宝和微信等支付接口的接入开发!没错,但支付接口的开发算是比较简单的了,我觉得凡是跟钱有关系的操作最重要的是事务问题,这一点很重要,很重要,真的很重要!LeanCloud 官方文档中有提到 MongoDB 不支持事务,并建议对事务有强烈需求的开发者使用其他折中方式来实现。我们的支付必须用事务,我们经过 N 轮讨后论设计了一套基于 LeanCloud 的支付场景的通用解决方案,也许其他团队比我们做得好,在这里还是分享下我们的一些见解吧。
我们在用户表 _User 中加入了一个 paylogs 字段,类型是 Array,主要用于存放着每一次支付日志的 id,用它来判断用户的账户 account 的值,比如钱扣没扣,加没加等情况。因为在支付过程中不能保证每一次操作都成功,所以还要引入一个日志表 log 来做数据的一致性,保证用户资金变动与实际相符。log 表里有一个「状态」字段 state,它的取值为 0 ~ 5,主要是从发起支付开始,生成 order 表,生成 log 表等,并记录 log 的状态,后续所有的业务都要根据 state 的状态执行不同的业务操作,不管在哪个状态出问题都可以根据 log表的 state 状态重复执行相应的业务操作,从而保证支付过程的数据一致性!
比如在充值的时候,用户扣费成功后,修改用户的 account 值成功了,但在修改 state 字段时失败了,下一次再执行时又怎么判断用户的 account 值已经改变了呢?这个问题真是太重要了,这就要用到那个 paylogs 字段,判断 paylogs 字段是否有值,八戒影院有值说明刚才用户的 account 值已经操作过了,此时可以不用操作,如果没有再进行操作。这里利用了 LeanCloud 数据存储接口的按条件更新数据的功能(使用 query 参数)来保证操作的原子性,从而也解决了并发问题!这个 query 参数真得要夸一下,在 LeanCloud 还没提供这个功能之前,我们只能采用 log 表中的新旧值比对来解决数据一致问题,但无法避免并发问题,这样当用户数据错了,我们只能认为支付失败,然后进入人工干预环节,很是麻烦。
最后再说说我们和 LeanCloud 的相遇。最初是通过朋友圈知道了 LeanCloud,后来就一直关注着。也试过一些项目,发现开发应用真是方便许多。原本大量的后端需求都要自己研发,现在都省了,只需要专注于写应用端的代码,效率自然会提高一倍以上,开发迭代速度也上去了。当然也有过顾虑,生怕遇到一些特殊场景 LeanCloud 满足不了那我们就悲剧了!但后来看到一些知名的应用都在用 LeanCloud,心里也就安稳了,有前辈们踩过坑,有 LeanCloud 的技术支持做后盾,我们就这样选定了 LeanCloud。
随着项目的进行,我们从传统的后端服务接口开发变成了面向「Document」开发,服务端工作减轻了不少。虽然在数据设计中遇到一些复杂结构的问题,比如 Pointer 和 Relations 的问题。记得当时 Array 不支持 Pointer 的 include,所以考虑用 Relations,但在 LeanCloud 社区中又看到几个相关问题都推荐使用 Array 或者 Pointer,后来通读了相关文档对数据模型有了更深的理解,问题也就少了,所以说全面了解文档是至关重要的。
在 MongoDB 上模拟事务操作来实现支付的更多相关文章
- mysql数据库和mongodb数据库的相关操作以及两个数据库的区别
在docs命令中执行数据操作 MySQL数据库 先启动MySQL服务器 net start mysql 进入MySQL服务器MySQL -uroot -p(这里写你的数据库密码) (-P是从哪个端口 ...
- Android随笔之——模拟按键操作的几种方式
前几天转过一篇Android上模拟按键操作.触屏事件的博客,昨天又去找了百度.谷歌了一下,写了一点简单的测试代码,留待不时之需.有需要看之前转载的那篇博客的请看这里→_→转:Android随笔之——使 ...
- MongoDB模拟多文档事务操作
Mongodb不支持多文档原子性操作,因此依据两阶段提交协议(Two Phase Commits protocol)来模拟事务. 以两个银行账户之间的转账行为为例,来说明如何实现多文档间的事务操作. ...
- 在Windows上使用终端模拟程序连接操作Linux以及上传下载文件
在Windows上使用终端模拟程序连接操作Linux以及上传下载文件 [很简单,就是一个工具的使用而已,放这里是做个笔记.] 刚买的云主机,或者是虚拟机里安装的Linux系统,可能会涉及到在windo ...
- C++基础——模拟事务 (1)COMMAND模式
=================================版权声明================================= 版权声明:原创文章 禁止转载 请通过右侧公告中的“联系邮 ...
- 使用JDBC进行数据库的事务操作(2)
本篇将讲诉如何使用JDBC进行数据库有关事务的操作.在上一篇博客中已经介绍了事务的概念,和在MySQL命令行窗口进行开启事务,提交事务以及回滚事务的操作. 似乎事务和批处理都可以一次同时执行多条SQL ...
- 使用JDBC进行数据库的事务操作(1)
本篇讲述数据库中非常重要的事务概念和如何使用MySQL命令行窗口来进行数据库的事务操作.下一篇会讲述如何使用JDBC进行数据库的事务操作. 事务是指数据库中的一组逻辑操作,这个操作的特点就是在该组逻辑 ...
- Spring中的事务操作
事务的特性 原子性:强调事务的不可分割. 一致性:事务的执行的前后数据的完整性保持一致. 隔离性:一个事务执行的过程中,不应该受到其他事务的干扰. 持久性:事务一旦结束,数据就持久化到数据库. 如果不 ...
- MongoDB: 原子性和事务
在MongoDB中, 文档级别的的写操作是原子性的, 甚至是在对某个文档的操作中修改其多个内嵌的子文档, 也是原子性的. 在一个写操作同时修改多个文档的情况, 对其中单独的某个文档而言是原子的, 但是 ...
随机推荐
- C#在派生类中调用基类成员
一.在派生类中调用基类成员 在C#的派生类中,我们可以使用base关键字调用基类中的公有或者受保护成员.这些成员只能是构造函数.实例方法或者实例属性. base关键字调用基类成员的语法格式如下: ba ...
- java基础 xml 使用dom4j解析 xml文件 servlet根据pattern 找到class
package com.swift.kaoshi; import java.io.File; import java.util.List; import java.util.Scanner; impo ...
- ES5 与 ES6六大不同
1.类Class 2.模块Module 导出变量 导出函数 导入 3.箭头函数 4.不再支持Mixins. 5.ES6不再支持自动绑定.
- vue2.0之监听属性的使用心得及搭配计算属性的使用
我们在工作中常常需要监听某一个属性值的变化,这个时候我们就需要用到了监听属性watch,在这里我总结watch属性的三种场景使用希望对你有所帮助: 1.基础版监听: 场景如下:输入框输入你的年龄,如果 ...
- Vscode插件--微信小程序格式化以及高亮组件wxml-vscode
wxml-vscode wxml-vscode 仓库 提问题 安装 通过 F1 或者 CMD + Shift + P 输入 install. 选择: Install Extension. 特性 格式化 ...
- hdu_2837_Calculation(欧拉函数,快速幂求指数循环节)
Assume that f(0) = 1 and 0^0=1. f(n) = (n%10)^f(n/10) for all n bigger than zero. Please calculate f ...
- phonegap二维码扫描插件
原文出处:http://rensanning.iteye.com/blog/2034026 谈谈我使用这个的体会吧; git地址 https://github.com/wildabeast/Barco ...
- datatable 默认按某字段排序
"columns": [ { data: null}, { data: 'name'}, { data: 'birthday'} ], "order": [[ ...
- vue组件封装及父子组件传值,事件处理
vue开发中,把有统一功能的部分提取出来,作为一个独立的组件,在需要使用的时候引入,可以有效减少代码冗余.难点在于如果封装,使用,如何传参,派发事件等,我会采取倒叙的方式进行说明.(本文总结于Vue2 ...
- JSON后台处理特殊字符方法,在JSONArray.fromObject转换时处理
/** * 替换一个字符串中的某些指定字符 * @param strData String 原始字符串 * @param regex String 要替换的字符串 * @param replaceme ...