中台 作者: lovingyu_er 时间: 2020-09-21 10:43:38 分类: 架构学习笔记, 技术品鉴 评论 ###中台建设的愿景 1. 中台只是解决问题的一种方案,不要把中台当成问题的本身。 2. 中台的愿景问题 3. 中台的用户和客户是谁? 4. 中台建设的钱从哪里来?众筹模式?投融资模式? 5. 中台建设虽然需要兼顾各方的利益,但更多主要还是解决企业管理层对于公司长期生存与可持续发展的恐惧与焦虑问题。 6. 中台的目标怎么验证?具体到一家企业某个中台的验证指标设计,这是一个复杂过程,而且往往还会不断演进,需要结合上面提到的中台愿景、投资模式、干系人利益点以及其他相关因素来综合设计。我们用到的一些思路和想法,我会在中台的规划与设计篇再为你展开来讲。 7. 企业孵化中台的企业环境是否已经成熟,这个是很重要的。有的企业最终没有成功反而是因为走得太早了,思路太超前了,周边环境还没有就绪。 ####中台建设规划建设方法论概述 企业级问题 公司企业的未来战略问题。 做中台本质上就是在做一个企业级的架构。一个融入了平台新要素的企业级架构。面向用户与创新的平台型企业架构。 #####中台架构D4模型 整体规划到落地交付
物联网平台的物模型 作者: lovingyu_er 时间: 2020-09-09 16:03:28 分类: 架构学习笔记 评论 ###介绍 是对设备在云端的功能描述,包括设备的**属性**、**服务**和**事件**。 物联网平台通过定义一种物的描述语言来描述物模型,称之为TSL(即 Thing Specification Language),采用JSON格式,您可以根据TSL组装上报设备的数据。 就是将实体设备进行数字化,并在云端构建该实体的数据模型。在物联网平台中,定义物模型即定义产品功能。完成功能定义后,系统将自动生成该产品的物模型。物模型描述产品是什么、能做什么、可以对外提供哪些服务。 分别从:属性,服务,事件三个维度来描述一个物理实体。 | 功能类型 | 说明| | :------------: | :------------: | | 属性(property) | 一般用于描述设备运行时的状态,如环境监测设备所读取的当前环境温度等。属性支持GET和SET请求方式。应用系统可发起对属性的读取和设置请求。 | | 服务(Service) | 设备可被外部调用的能力或方法,可设置输入参数和输出参数。相比于属性,服务可通过一条指令实现更复杂的业务逻辑,如执行某项特定的任务。 | | 事件 (event) | 设备运行时的事件。事件一般包含需要被外部感知和处理的通知信息,可包含多个输出参数。如,某项任务完成的信息,或者设备发生故障或告警时的温度等,事件可以被订阅和推送。| ###物模型格式 阿里云的物联网平台,你可以在设备管理产品中,有相关的设备信息: 您可以在产品的功能定义页面,单击**物模型TSL**,查看**JSON格式的TSL**。 重点:```properties```,```events```,```services``` ``` { "schema": "物模型结构定义的访问URL", "profile": { "productKey": "产品ProductKey" }, "properties": [ { "identifier": "属性唯一标识符(产品下唯一)", "name": "属性名称", "accessMode": "属性读写类型:只读(r)或读写(rw)。", "required": "是否是标准功能的必选属性", "dataType": { "type": "属性类型: int(原生)、float(原生)、double(原生)、text(原生)、date(String类型UTC毫秒)、bool(0或1的int类型)、enum(int类型)、struct(结构体类型,可包含前面7种类型)、array(数组类型,支持int/double/float/text/struct)", "specs": { "min": "参数最小值(int、float、double类型特有)", "max": "参数最大值(int、float、double类型特有)", "unit": "属性单位", "unitName": "单位名称", "size": "数组大小,默认最大128(数组特有)。", "step": "步长,字符串类型。", "item": { "type": "数组元素的类型" } } } } ], "events": [ { "identifier": "事件唯一标识符(产品下唯一,其中post是默认生成的属性上报事件。)", "name": "事件名称", "desc": "事件描述", "type": "事件类型(info、alert、error)", "required": "是否是标准功能的必选事件", "outputData": [ { "identifier": "参数唯一标识符", "name": "参数名称", "dataType": { "type": "属性类型: int(原生)、float(原生)、double(原生)、text(原生)、date(String类型UTC毫秒)、bool(0或1的int类型)、enum(int类型)、struct(结构体类型,可包含前面7种类型)、array(数组类型,支持int/double/float/text/struct)", "specs": { "min": "参数最小值(int、float、double类型特有)", "max": "参数最大值(int、float、double类型特有)", "unit": "属性单位", "unitName": "单位名称", "size": "数组大小,默认最大128(数组特有)。", "step": "步长,字符串类型。", "item": { "type": "数组元素的类型" } } } } ], "method": "事件对应的方法名称(根据identifier生成)" } ], "services": [ { "identifier": "服务唯一标识符(产品下唯一,其中set/get是根据属性的accessMode默认生成的服务。)", "name": "服务名称", "desc": "服务描述", "required": "是否是标准功能的必选服务", "callType": "async(异步调用)或sync(同步调用)", "inputData": [ { "identifier": "入参唯一标识符", "name": "入参名称", "dataType": { "type": "属性类型: int(原生)、float(原生)、double(原生)、text(原生)、date(String类型UTC毫秒)、bool(0或1的int类型)、enum(int类型)、struct(结构体类型,可包含前面7种类型)、array(数组类型,支持int/double/float/text/struct)", "specs": { "min": "参数最小值(int、float、double类型特有)", "max": "参数最大值(int、float、double类型特有)", "unit": "属性单位", "unitName": "单位名称", "size": "数组大小,默认最大128(数组特有)。", "step": "步长,字符串类型。", "item": { "type": "数组元素的类型" } } } } ], "outputData": [ { "identifier": "出参唯一标识符", "name": "出参名称", "dataType": { "type": "属性类型: int(原生)、float(原生)、double(原生)、text(原生)、date(String类型UTC毫秒)、bool(0或1的int类型)、enum(int类型)、struct(结构体类型,可包含前面7种类型)、array(数组类型,支持int/double/float/text/struct)", "specs": { "min": "参数最小值(int、float、double类型特有)", "max": "参数最大值(int、float、 double类型特有)", "unit": "属性单位", "unitName": "单位名称", "size": "数组大小,默认最大128(数组特有)。", "step": "步长,字符串类型。", "item": { "type": "数组元素的类型(数组特有)" } } } } ], "method": "服务对应的方法名称(根据identifier生成)" } ] } ```
Nginx搭建负载均衡 作者: lovingyu_er 时间: 2020-07-08 14:29:00 分类: 架构学习笔记, 技术品鉴,朝花夕拾 评论 ####负载均衡 关于负载均衡的定义,是一个比较好理解的概念,比较像小时候提水一样,一个人提会很累,再找一个人分担,两个人都会相对比较轻松一样,说白了就是分担了重量,负载均衡在这里就是相对来说就是分担流量,从而解决了单个节点压力过大,造成Web服务响应过慢的问题,避免了严重情况下导致服务瘫痪,而导致服务不能正常服务的问题。对于用户来说,如果你后台服务器挂掉一个,而仍能够正常访问,用户无感知,再加上```keepalived```,就可以自动剔除无效的web节点 ####搭建: ######1. 服务器准备: ``` 负载均衡服务器:172.31.56.229 web服务器1:172.31.56.228 web服务器2:172.31.56.230 ``` ######2. 安装nginx 三台服务器上全部安装服务器 ######3. 服务器配置: 负载均衡服务器配置(```172.31.56.229```) ``` upstream serverlist { server 172.31.56.230:8383 weight=1; server 172.31.56.228:8383 weight=1; } server { listen 80; server_name your.domain.com; location / { proxy_pass http://serverlist; } } ``` web服务器1的nginx配置(```172.31.56.228```): ``` server { listen 8383; root /home/darrykinger/test_slb/; # Add index.php to the list if you are using PHP index index.html index.php server_name serverlist; } ``` web服务器2的nginx配置(```172.31.56.230```): ``` server { listen 8383; root /home/ubuntu/test_slb/; index index.html index.htm index.nginx-debian.html; server_name serverlist; } ``` 每个主机,配置好以后,请```reload```一下```nginx```服务,访问你的域名就可以了,比如使用```curl```或者浏览器访问你的域名,注意:上述的**负载均衡服务器**的那台服务器,有一个公网IP地址,我配置了域名,用域名就可以直接访问了。这个案例只是个人实验,生产环境还要增加很多的安全限制。 注意:负载均衡是负载均衡,高可用是高可用,是两个独立的概念,前者是分流,后者是提供不间断的服务。
分佈式事務,有解嗎? 作者: lovingyu_er 时间: 2020-06-22 13:53:00 分类: 架构学习笔记,朝花夕拾 评论 文章連接來自: ```https://mp.weixin.qq.com/s/JuNTuO-b_DdNNOdnwfqwHg```(微信公众号:58架构师) #####1. 单库,多个数据要同时操作,如何保证数据的完整性,以及一致性? 答:事务。 举个栗子: 用户下了一个订单,需要修改余额表,订单表,流水表,于是会有类似的伪代码: start transaction; CURD table t_account; any Exception rollback; CURD table t_order; any Exception rollback; CURD table t_flow; any Exception rollback; commit; 如果对余额表,订单表,流水表的SQL操作全部成功,则全部提交 如果任何一个出现问题,则全部回滚 事务,可保证数据的完整性以及一致性。 #####2. 多库环境下,事务的方案会有什么潜在问题? 答:互联网的业务特点,数据量较大,并发量较大,经常使用拆库的方式提升系统的性能。 如果进行了拆库,余额、订单、流水可能分布在不同的数据库上,甚至不同的数据库实例上,此时就不能用数据库原生事务来保证数据的一致性了。 #####3. 高并发易落地的分布式事务,是行业没有很好解决的难题,那怎么办呢? 答:补偿事务是一种常见的实践。 #####4. 什么是补偿事务? 答:补偿事务,是一种在业务端实施业务逆向操作事务。 举个栗子: 修改余额,事务为: int Do_AccountT(uid, money){ start transaction; //余额改变money这么多 CURD table t_account with money for uid; anyException rollback return NO; commit; return YES; } 那么,修改余额,补偿事务可以是: int Compensate_AccountT(uid, money){ //做一个money的反向操作 return Do_AccountT(uid, -1*money){ } 同理,订单操作,事务是:Do_OrderT,新增一个订单; 订单操作,补偿事务是:Compensate_OrderT,删除一个订单。 要保证余额与订单的一致性,伪代码: // 执行第一个事务 int flag = Do_AccountT(); if(flag=YES){ //第一个事务成功,则执行第二个事务 flag= Do_OrderT(); if(flag=YES){ // 第二个事务成功,则成功 return YES; } else{ // 第二个事务失败,执行第一个事务的补偿事务 Compensate_AccountT(); } } #####5. 补偿事务有什么缺点? 不同的业务要写不同的补偿事务,不具备通用性; 没有考虑补偿事务的失败; 如果业务流程很复杂,if/else会嵌套非常多层; 画外音:上面的例子还只考虑了余额+订单的一致性,就有2*2=4个分支,如果要考虑余额+订单+流水的一致性,则会有2*2*2=8个if/else分支,复杂性呈指数级增长。 还有其它简易一致性实践么? 答:多个数据库实例上的多个事务,要保证一致性,可以进行“后置提交优化”。 单库是用这样一个大事务保证一致性: start transaction; CURD table t_account; any Exception rollback; CURD table t_order; any Exception rollback; CURD table t_flow; any Exception rollback; commit; 拆分成了多个库后,大事务会变成三个小事务: start transaction1; //第一个库事务执行 CURD table t_account; any Exception rollback; … // 第一个库事务提交 commit1; start transaction2; //第二个库事务执行 CURD table t_order; any Exception rollback; … // 第二个库事务提交 commit2; start transaction3; //第三个库事务执行 CURD table t_flow; any Exception rollback; … // 第三个库事务提交 commit3; 画外音:再次提醒,这三个事务发生在三个库,甚至3个不同实例的数据库上。 一个事务,分成执行与提交两个阶段: 执行(CURD)的时间很长 提交(commit)的执行很快 于是整个执行过程的时间轴如下:  第一个事务执行200ms,提交1ms; 第二个事务执行120ms,提交1ms; 第三个事务执行80ms,提交1ms; 在什么时候,会出现不一致? 答:第一个事务成功提交之后,最后一个事务成功提交之前,如果出现问题(例如服务器重启,数据库异常等),都可能导致数据不一致。  画外音:如上图,最后202ms内出现异常,会出现不一致。 什么是后置提交优化? 答:如果改变事务执行与提交的时序,变成事务先执行,最后一起提交。  第一个事务执行200ms,第二个事务执行120ms,第三个事务执行80ms; 第一个事务提交1ms,第二个事务提交1ms,第三个事务提交1ms; 后置提交优化后,在什么时候,会出现不一致? 答:问题的答案与之前相同,第一个事务成功提交之后,最后一个事务成功提交之前,如果出现问题(例如服务器重启,数据库异常等),都可能导致数据不一致。  画外音:如上图,最后2ms内出现异常,会出现不一致。 有什么区别和差异? 答: 串行事务方案,总执行时间是303ms,最后202ms内出现异常都可能导致不一致; 后置提交优化方案,总执行时间也是303ms,但最后2ms内出现异常才会导致不一致; 虽然没有彻底解决数据的一致性问题,但不一致出现的概率大大降低了。 画外音:上面这个例子,概率降低了100倍。 后置提交优化,有什么不足? 答:对事务吞吐量会有影响: 串行事务方案,第一个库事务提交,数据库连接就释放了; 后置提交优化方案,所有库的连接,要等到所有事务执行完才释放; 这就意味着,数据库连接占用的时间增长了,系统整体的吞吐量降低了。 总结 分布式事务,两种常见的实践: 补偿事务 后置提交优化 把 trx1.exec(); trx1.commit(); trx2.exec(); trx2.commit(); trx3.exec(); trx3.commit(); 优化为: trx1.exec(); trx2.exec(); trx3.exec(); trx1.commit(); trx2.commit(); trx3.commit(); 这个小小的改动(改动成本极低),不能彻底解决多库分布式事务数据一致性问题,但能大大降低数据不一致的概率,牺牲的是吞吐量。 对于一致性与吞吐量的折衷,还需要业务架构师谨慎权衡折衷。 画外音:还是那句话,一切脱离业务常见的架构设计,都是耍流氓。
17.消息队列:秒杀时如何处理每秒上万次的下单请求?学习笔记 作者: lovingyu_er 时间: 2020-01-21 21:07:00 分类: 架构学习笔记, 技术品鉴 评论 ####高并发设计的三个目标 性能,可用性和高扩展性 高并发的一般都是查询,读多写少。 消息队列在秒杀场景下的作用: ###1.削去秒杀场景下的峰值写流量 四个字概括就是:削峰填谷 也就是说它可以削平短暂的流量高峰,虽说堆积会造成请求被短暂延迟处理,但是只要我们时刻监控消息队列中的堆积长度,在堆积量超过一定量时,增加队列处理机数量来提升消息的处理能力就好了,而且秒杀的用户对于短暂延迟知晓秒杀的结果也是有一定容忍度的。 ###2.通过异步处理简化秒杀请求中的业务流程 你想,在秒杀场景下,我们整个购买请求处理完成需要 500ms。这时你分析了一下整个的购买流程,发现这里面会有主要的业务逻辑,也会有次要的业务逻辑, 我们分析到的主要的流程是生成订单、扣减库存; 次要的流程可能是我们在下单购买成功之后会给用户发放优惠券,会增加用户的积分。 也就是将次要的流程从整个业务逻辑中分离出来,不和主要业务逻辑同步,这样就又减少了整个业务流程的处理时长。 如果发放优惠券需要耗时50ms,增加用户积分也是50ms,那么将缩短整个流程的100ms的时长,那么整个购买请求处理完成需要的时间降低到400ms,大大的优化了系统的性能。 ###3.解耦实现秒杀系统模块之间松耦合 功用:解耦合 新需求: 比如数据团队对你说,在秒杀活动之后想要统计活动的数据,借此来分析活动商品的受欢迎程度、购买者人群的特点以及用户对于秒杀互动的满意程度等等指标。而我们需要将大量的数据发送给数据团队,那么要怎么做呢? 一般的思路,使用http或者rpc的方式来同步的调用,也就是直接给数据团队一个接口,同步将数据放松给数据团队。 那么这种思路在高并发的秒杀系统中存在的问题: - 耦合性比较强,如果数据团队接口出现异常,影响秒杀的进行 - 数据系统变更数据字段的时候,接口也要变更字段,秒杀系统要跟着更改。 使用消息队列后的解决思路如下:秒杀系统产生一条购买数据后,我们可以先把全部数据发送给消息队列,然后数据团队再订阅这个消息队列的话题,这样它们就可以接收到数据,然后再做过滤和处理了。 本小结,主要是讲了在秒杀系统场景下,消息队列的作用,整理起来就是:削峰填谷,异步处理,解耦合。 在公司项目设计中,由于业务监听部分,需要检测返回的数据是否正常,发送邮件的功能,就用到消息队列。包括一些search功能,采集用户的搜索记录等等。