当前位置: 首页 > news >正文

用户数量高达3人的分布式系统

稍微有一些项目经验之后,如果再深入下去,可能会接触到高并发、分布式,相关的工具集和技术有:并发编程、分布式事务、Redis、数据库集群、消息队列、Hadoop、微服务……总之你能张嘴喷出来的高大上的词汇越多,就越显得你厉害,足以让新手自卑,让外行赞叹。

我差点就走上这条不归路。无数次的事实已经证明:没有最好的技术,只有最合适的技术。如果脱离实际场景去照抄别人的解决方案,结果只能是东施效颦。我听过不少人高呼:解决分布式问题,一定要用分布式事务。你要是给他个赞许的目光,他一会儿就能接着侃侃而谈:CAP理论、柔性事务……说了个把钟头,他甚至都没关心具体的业务是什么。

我们假设这样一种场景:系统A和上游系统保持TCP长连接,上游不断地给A发送消息,而A要对每条消息做到尽快地处理,上游发送消息的频率是相当高的:超过100MPS(message per second)。系统A用了队列缓存接收到的消息,然后从队列中不断取出消息进行处理。处理结果要持久化,然后通知下游系统。这样的场景下,使用关系数据库必然是致命的。用消息队列呢,很遗憾传统的mq也不能满足要求,mq并不能加快一个事务的处理速度,说白了,mq就是个远程的队列,最大的作用就是缓冲压力,也就是所谓的削峰填谷,和实时处理完全就是相悖的。

那么Redis能解决我们的问题吗?并不能。我已经不止一次见到有人拿Redis当“比较快的数据库”来用,直接进行处理结果写入,写到redis就想当然的认为业务处理成功了,真是勇气可嘉。回到系统A,快速的处理一个事务并进行持久化的关键在于两点:
1、让事务尽可能简单
2、采用追加写入的方式进行持久化,比如LevelDb(微秒级写速度)、或者自己用相关的文件操作类也可以
第2点很简单,那如何让事务的处理尽可能简单呢?传统的事务处理就是因为过多的磁盘读写操作拖了后腿。到这里解决办法已经很清晰了:我们只记录动作,不记录数据。毕竟有了所有的动作,就有了所有的数据,mysql的binlog差不多就是这么个思路。缓存解决了读的问题,db操作不过就剩下:增加、删除、编辑这三类写操作,如果我们不直接操作数据,而是只记录类似“增加了数据A”,“删除了数据B”这样的动作(我们又称之为事件),那么依据这些事件,我们就可以从0重演出整个系统的状态。

针对系统A的场景,我们最终的解决办法是:
1、全内存运行
2、每次事务只存储事件

带来的好处之一:业务逻辑没有任何db操作,持久化事件完全可以封装在消息入口处,业务Handler纯内存操作,而且由一个线程调度,进而完全避免了多线程并发问题;
带来的好处之二:系统有了重放事件的能力,可以精确还原用户每次操作的数据场景,对重现bug意义重大。

天下没有免费的午餐,就算是西北风,也得自己张嘴去喝。

带来的坏处是:新技术(其实是多年前老掉牙的技术了,对我们团队来说是新的尝试)带来新问题,前期的框架修修补补,因为要做成分布式的,所以主节点和从节点需要事件同步,以保持程序状态的一致,好在这些问题是框架层面的,解决一次就行了。

重申一下:解决任何问题都得看具体场景。如果对实时处理没有苛刻的要求,做好缓存和代码优化,对付一般的应用场景完全足够了,分布式也好、redis也好、mq也罢能不用就不用,不考虑场景硬是尬用各种框架、工具无异于往自己身上滥贴狗皮膏药。

尽量不要用那些看似高大上的技术,任何东西都有成本,面对一个明明用CRUD就足以解决的小系统,要是我们张口闭口就是高并发、分布式,吭哧吭哧把自己累得跟孙子似的的搞出了所谓的分布式架构,一上线,同时在线用户高达3人——你说尴尬不尴尬。

转载于:https://www.cnblogs.com/qzhforthelife/p/9758087.html

相关文章:

  • 多研究些架构,少谈些框架——一名阿里架构师的笔记
  • 深入浅出Node.js
  • unix下命令窗分屏工具
  • linux防火墙操作随笔记录
  • CF1060E Sergey and Subway(点分治)
  • CentOS 7更改yum源与更新系统
  • Python基本数据类型集合、格式化、函数
  • 印章与合同管理一体化:杜绝实体印章与纸质合同隐患
  • 微软正式发布Azure Functions 2.0
  • 微信小程序所带来的机会
  • CLTPHP5.0发布
  • 支付宝小程序
  • 23、【支付模块开发】——Java对接支付宝步骤(沙箱环境)
  • karabiner json语法
  • Java反射-动态类加载和重新加载
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • ECS应用管理最佳实践
  • JDK 6和JDK 7中的substring()方法
  • JS基础篇--通过JS生成由字母与数字组合的随机字符串
  • Koa2 之文件上传下载
  • Linux快速配置 VIM 实现语法高亮 补全 缩进等功能
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • Python进阶细节
  • 包装类对象
  • 翻译--Thinking in React
  • 模仿 Go Sort 排序接口实现的自定义排序
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 它承受着该等级不该有的简单, leetcode 564 寻找最近的回文数
  • RDS-Mysql 物理备份恢复到本地数据库上
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • #中国IT界的第一本漂流日记 传递IT正能量# 【分享得“IT漂友”勋章】
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (4) openssl rsa/pkey(查看私钥、从私钥中提取公钥、查看公钥)
  • (Redis使用系列) Springboot 在redis中使用BloomFilter布隆过滤器机制 六
  • (笔试题)合法字符串
  • (草履虫都可以看懂的)PyQt子窗口向主窗口传递参数,主窗口接收子窗口信号、参数。
  • (二)JAVA使用POI操作excel
  • (翻译)Entity Framework技巧系列之七 - Tip 26 – 28
  • (六) ES6 新特性 —— 迭代器(iterator)
  • (算法)求1到1亿间的质数或素数
  • (转)全文检索技术学习(三)——Lucene支持中文分词
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • *p=a是把a的值赋给p,p=a是把a的地址赋给p。
  • .apk 成为历史!
  • .a文件和.so文件
  • .NET CF命令行调试器MDbg入门(三) 进程控制
  • .NET Core 网络数据采集 -- 使用AngleSharp做html解析
  • .NET Framework .NET Core与 .NET 的区别
  • .NET 分布式技术比较
  • .NET 解决重复提交问题
  • .net的socket示例
  • .net和php怎么连接,php和apache之间如何连接
  • .net实现客户区延伸至至非客户区
  • @Documented注解的作用
  • [20140403]查询是否产生日志