导读
明代著名的心学集大成者王阳明先生在《传习录》中有云:“道无精粗,人之所见有精粗。如这一间房,人初进来,只见一个大规模如此。处久,便柱壁之类,一一看得明白。再久,如柱上有些文藻,细细都看出来。然只是一间房。”是的,知识理论哪有什么精粗之分,只是人的认识程度不同而已。笔者在技术圈摸爬滚打数年,接触了各式各样的 Java 服务端架构,见得多了自然也就认识深了,就能分辨出各种方案的优劣了。这里总结了一些初创公司存在的 Java 服务端问题,并尝试性地给出了一些解决方案,供大家交流参考。
系统不是分布式
单机版系统抢单案例
// 抢取订单函数
public synchronized void grabOrder(Long orderId, Long userId) {
// 获取订单信息
OrderDO order = orderDAO.get(orderId);
if (Objects.isNull(order)) {
throw new BizRuntimeException(String.format("订单(%s)不存在", orderId));
}
// 检查订单状态
if (!Objects.equals(order.getStatus, OrderStatus.WAITING_TO_GRAB.getValue())) {
throw new BizRuntimeException(String.format("订单(%s)已被抢", orderId));
}
// 设置订单被抢
orderDAO.setGrabed(orderId, userId);
}
以上代码,在一台服务器上运行没有任何问题。进入函数 grabOrder(抢取订单)时,利用 synchronized 关键字把整个函数锁定,要么进入函数前订单未被人抢取,从而抢单成功,要么进入函数前订单已被抢取导致抢单失败,绝对不会出现进入函数前订单未被抢取而进入函数后订单又被抢取的情况。
但是,如果上面的代码在两台服务器上同时运行,由于 Java 的 synchronized 关键字只在一个虚拟机内生效,所以就会导致两个人能够同时抢取一个订单,但会以最后一个写入数据库的数据为准。所以,大多数的单机版系统,是无法作为分布式系统运行的。
分布式系统抢单案例
添加分布式锁,进行代码优化:
// 抢取订单函数
public void grabOrder(Long orderId, Long userId) {
Long lockId = orderDistributedLock.lock(orderId);
try {
grabOrderWithoutLock(orderId, userId);
} finally {
orderDistributedLock.unlock(orderId, lockId);
}
}
// 不带锁的抢取订单函数
private void grabOrderWithoutLock(Long orderId, Long userId) {
// 获取订单信息
OrderDO order = orderDAO.get(orderId);
if (Objects.isNull(order)) {
throw new BizRuntimeException(String.format("订单(%s)不存在", orderId));
}
// 检查订单状态
if (!Objects.equals(order.getStatus, OrderStatus.WAITING_TO_GRAB.getValue())) {
throw new BizRuntimeException(String.format("订单(%s)已被抢", orderId));
}
// 设置订单被抢
orderDAO.setGrabed(orderId, userId);
}
优化后的代码,在调用函数 grabOrderWithoutLock(不带锁的抢取订单)前后,利用分布式锁 orderDistributedLock(订单分布式锁)进行加锁和释放锁,跟单机版的 synchronized 关键字加锁效果基本一样。
分布式系统的优缺点
分布式系统(Distributed System)是支持分布式处理的软件系统,是由通信网络互联的多处理机体系结构上执行任务的系统,包括分布式操作系统、分布式程序设计语言及其编译系统、分布式文件系统分布式数据库系统等。
分布式系统的优点:
- 可靠性、高容错性:
一台服务器的崩溃,不会影响其它服务器,其它服务器仍能提供服务。
- 可扩展性:
如果系统服务能力不足,可以水平扩展更多服务器。
- 灵活性:
可以很容易的安装、实施、扩容和升级系统。
- 性能高:
拥有多台服务器的计算能力,比单台服务器处理速度更快。
- 性价比高:
分布式系统对服务器硬件要求很低,可以选用廉价服务器搭建分布式集群,从而得到更好的性价比。
分布式系统的缺点:
- 排查难度高:
由于系统分布在多台服务器上,故障排查和问题诊断难度较高。
- 软件支持少:
分布式系统解决方案的软件支持较少。
- 建设成本高:
需要多台服务器搭建分布式系统。
曾经有不少的朋友咨询我:”找外包做移动应用,需要注意哪些事项?”
首先,确定是否需要用分布式系统。软件预算有多少?预计用户量有多少?预计访问量有多少?是否只是业务前期试水版?单台服务器能否解决?是否接收短时间宕机?……如果综合考虑,单机版系统就可以解决的,那就不要采用分布式系统了。因为单机版系统和分布式系统的差别很大,相应的软件研发成本的差别也很大。