分布式环境中,处理并发问题没发通过操作系统和 JVM 提供的工具来解决,因为 LOCK 命令、总线锁、缓存所、monitor 对象、锁、等并发工具都无法影响到其他服务器的线程。
那么在分布式环境中,可以使用一下策略和方式处理:
- 避免并发
- 通过某些策略和业务来避免并发,如合理分配时间调度,避开共享资源的存取冲突等。
- 可以通过 hash 算法的方式,使一个对象的数据计算和访问都交给同一个线程来完成
- 时间戳
- 每次系统 A 发送给系统 B 的时候都带上一个时间戳,B 在拿到通知后,比较时间戳
- 这样只需要调用方保证时间戳的时序有效性即可
- 串行化
- 串行化可能产生并发的问题,通过牺牲性能和扩展性,来满足对数据一致性的要求。
- 比如分布式消息系统,没法保证消息的有序性,但是可以通过将分布式消息系统改为单一消息系统,就可以保证消息的有序性了。
- 如果接收方无法保证处理的有序性,那么可以使用一个队列将调用信息缓存起来,再串行地处理这些调用
- 数据库
- 在分布式环境中,数据库是个服务器的共享点,可以通过数据库的高可靠一致性机制来满足需求。
- 比如通过唯一性约束,来解决并发过程中重复数据的生产或重复任务的执行
- 某些更新操作也尽量使用 SQL 来完成,在程序中计算后再更新,可能会出现脏复写的问题,但是通过一条 SQL 来完成计算和更新,就能通过数据库的锁机制来保证更新的一致性
- 行锁
- 有些事务较为复杂时,无法通过一条 SQL 解决问题,并且可能存在并发问题,此时可以考虑使用行锁来解决问题
- 如 select … for update ,在查询后将该行数据锁定,直到 commit。但是这么做会导致其他涉及该行的所有操作都会被挂起
- 通过在表中增加一个标志锁的字段,每次操作之前通过 update,来模拟竞争锁的操作,操作完成后再 update 复位该标志,表示锁归还。(这种操作很类似 Redis 分布式锁、MongoDB 分布式锁,说白了就是自己定义一个模拟竞争锁的场景)
- 统一触发途径
- 如果一个数据会被多个业务同时涉及到,就会有并发问题产生的隐患。因此可以通过前期架构和业务涉及,尽量统一触发途径,减少并发的可能,也有利于对并发问题的分析和判断。
文章总结自 : https://blog.csdn.net/cutesource/article/details/5791350