订单系统:https://mp.weixin.qq.com/s/Q554hF7Vt0FHUZAQkSc62w

项目一:乐海游

人员:一个前端,三个后台,一个测试,一个UI

邮轮,打造旅游生态,主营邮轮旅游业务,附加了一些门票,专车接送,酒店住宿,美食娱乐,

除了邮轮数据是自己的,景点和酒店都是对接外界的api,中间赚点差价,主营邮轮旅游,各个模块互不影响。

流程:

用户进入页面,展示商品,数据库查询业务,包车结算,不同的api调用,如果是门票酒店等就是第三方api提供,如果是邮轮旅游则是自己的接口,下完订单后会保存订单信息,后续会进行一个跟踪,可能状态修改,搜索展示,下单翻页,跳转,数据库的记录,更改

比较复杂的还是在数据库的设计上,因为每种邮轮底下有多个邮轮,每个邮轮又关联着许多子业务,有服务,美食,娱乐这些东西,然后每种子业务又有具体的东西。因为关系比较复杂,所以我在这边用了 Solr进行分布式搜索 来提高查询效率

solr

(2)Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能。

(3)Solr 支持更多格式的数据,比如JSON、XML、CSV,而 Elasticsearch 仅支持json文件格式。

(4)Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供

(5)Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于 Elasticsearch。

(6)Solr 是传统搜索应用的有力解决方案,但 Elasticsearch 更适用于新兴的实时搜索应用。

为什么选择solr,在项目怎么使用的

航线搜索中使用,航线比较多。

传统的是:找出所有包含关键词的文档,这样依次从文档中去查找是否含有关键词的方法叫做正向索引,为了增加效率,搜索引擎会把正向索引变为反向索引(倒排索引)即把“文档→单词”的形式变为“单词→文档”的形式

image-20240321204551766

memchached

Memcacehd的工作流程

先检查客户端的请求数据是否在memcached中,如有,直接把请求数据返回,不再对数据库进行任何操作;如果请求的数据不在memcached中,就去查数据库,把从数据库中获取的数据返回给客户端,同时把数据缓存一份到memcached中(memcached客户端不负责,需要程序明确实现);每次更新数据库的同时更新memcached中的数据,保证一致性;当分配给memcached内存空间用完之后,会使用LRU(Least Recently Used,最近最少使用)策略加上到期失效策略,失效数据首先被替换,然后再替换掉最近未使用的数据。

与redis比较

1.Redis不仅仅支持简单的k/v类型的数据,同时还提供string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)等数据结构的存储。memcache支持简单的数据类型,String。

2.Redis支持数据的备份,即master-slave模式的数据备份。

3.Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,而Memecache把数据全部存在内存之中

4.redis的速度比memcached快很多

5.Memcached是多线程,非阻塞IO复用的网络模型;Redis使用单线程的IO复用模型。

​ 小结:,有持久化需求或者对数据结构和处理有高级要求的应用,选择redis,其他简单的key/value存储,选择memcached。对于两者的选择需要要看具体的应用场景,如果需要缓存的数据只是key-value这样简单的结构时,则还是采用memcache,它也足够的稳定可靠。如果涉及到存储,排序等一系列复杂的操作时,毫无疑问选择redis。

邮轮旅游模块场景:

选择航线,选择邮轮,不同的邮轮然后里面就有餐厅,住宿等定制化服务,还有洗衣服,提供早餐等增值服务

项目二茶电商平台

外包项目,回学校了不知道后面的具体情况

b2b, b2c的平台,茶叶茶具一体化服务,用到的技术,dubbo,zookeeper,

项目介绍

“优茶联”是一个B2B,B2C的茶电商平台。这个项目是由SpringMVC框架搭建的,将系统分成多层进行解耦合。因为业务服务比较多,所以这边用了Dubbo分布式服务框架来进行协调不同层次之间的服务调用。而Dubbo组件中有一个Registry也就是注册中心,我们这边选了Zookeeper作为Dubbo服务的注册中心,进行服务的注册和订阅。然后平时会搞一些促销活动,并发量会比较大,所以这边用RabbitMQ消息队列进行消息的传递,避免数据库压力过大,也保证了用户使用过程的顺畅性。我在项目中主要负责的是微信商城的订单模块的后台开发。后台开发时遇到的困难就是创建预售订单的业务问题,后来通过网上看了人人都是产品经理的文章里面的一张架构流程图,然后我这边就设定预售商品和普通商品不能同时创建订单,预售商品不加入购物车,不走库存。

介绍项目干嘛的+技术栈+技术栈对应干嘛的+负责干的什么

微信商城后台订单模块开发

完成跨端调用,选择商品,下单,支付的过程,然后收到短信,从0到1的微信下单的过程。

项目为什么要用到分布式:将传统的大的集成平台系统分成几个小的系统,以往的平台一个系统如果宕机完蛋,但是现在商品,库存,布置在不同的服务器上其他功能不受影响。dubbo的话,就是因为不同模块调用不同的服务,web端,pc端,微信端,不同端的接口不可能重新写一。

dubbo的应用场景:我做的系统中我要调用一个加入购物车的操作,无论什么端都会落实到同一个数据库,接口写成通用的,微信端不能直接调用,用rpc远程调用不能直接导包调用,用dubbo的注册,消费服务的功能

Dubbo:

​ 是一个分布式服务框架,以及SOA治理方案。其功能主要包括:高性能NIO通讯及多协议集成,服务动态寻址与路由,软负载均衡与容错,依赖分析与降级等。 它有5个节点,分别是Provider, Consumer, Registry, Monitor, Container。其中Provider是服务提供者, Consumer是服务消费者,Registry是服务进行注册和被发现的注册中心,Monitor是统计服务的调用次数和调用时间的监控中心,Container是服务运行容器。他们之间调用的关系是:Container负责启动,加载然后运行Provider。Provider在启动时会向注册中心注册自己提供的服务,Consumer在启动时会向Registry订阅自己所需服务,此时Registry会返回Provider地址列表给Consumer。如果地址有变更,Registry会基于长连接推送变更数据给Consumer。Consumer会基于软负载均衡算法选一台提供者进行调用,如果调用失败,则再选一台。Provider和Consumer在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到Monitor。 Dubbo具有4个特点,分别是连通性、健壮性、伸缩性、以及向未来架构的升级性。连通性说明他们之间都存在着关系,比如说Provider,Consumer和Registry三者之间都是长连接,而Provider,Consumer向Registry注册服务以及订阅服务的时间都得向Monitor汇报。而健壮性说明具有稳定性,比如说注册中心对等集群中的任意一台宕掉后,将自动切换到另一台。就算注册中心全部宕掉,服务者和消费者仍可以通过本地缓存进行通讯。而伸缩性就是可以通过增加机器部署实例进行添加新的注册中心和服务提供者。而升级性是文档中提到的对未来架构的设想,比起目前框架它的特点是可以实现自动部署服务的本地代理以及可以通过访问压力来自动增减服务提供者。

image-20240308162213018

简述Zookeeper:

主要是管理多个机器的监察情况,负载均衡,处理信息,dubbo的服务的注册和订阅中心是zookeeper,确保服务之间的通信和协调

Zookeeper 为分布式应用提供了一个高效可靠的分布式协调服务。它实现是依赖于 ZAB 协议,实现了一种主备模式的架构来保持集群中数据的一致性。Zookeeper 使得分布式应用可以通过一个共享的树形结构的命名空间实现协调。它还将所有的数据存储在内存中。Zookeeper 集群中的任何一台机器都可以响应客户端的读操作,且全量数据存在于内存中,因此 Zookeeper 更适合以读操作为主的应用场景。

Zookeeper作为Dubbo的注册中心时:服务提供者在初始化启动时,会在Zookeeper下的Dubbo节点下的服务节点下的providers节点下的节点创建一个子节点并写入URL,路径类似为 /dubbo/servicename/providers/ ,该路径下的所有子节点均为服务提供者。此时这些子节点都为临时节点,因为临时节点的生命周期与客户端会话相关,所以一旦提供者所在的机器出现故障导致提供者无法提供服务,该临时节点就会自动从Zookeeper删除。此时因为服务者,注册中心,消费者之间是长连接,注册中心能感知服务者宕机,会告知消费者。而监控中心是Dubbo服务治理体系中重要的一部分,它需要知道所有的服务提供者和消费者的变化情况 。所以它在启动时会在服务节点上注册一个watcher来监听子节点变化,路径为 /dubbo/servicename/ ,所以它也能感知服务提供者的宕机。服务消费者的节点创建过程和提供者是一样的,而且也是临时结点。还有一个特性就是Zookeeper的节点结构设计,它以服务名和类型,也就是 /dubbo/servicename/类型 作为节点路径,符合Dubbo订阅和通知的需求,保证了以服务为粒度的变更通知,通知范围易于控制。所以即使服务提供者和消费者频繁变更,对Zookeeper的性能也不会造成多大影响。

3.Zookeeper的某个机器挂了,整个集群如何处理?

​ 不是leader则其他的还可以用

​ Zookeeper采用了分布式的架构,具有多个服务器节点构成一个集群。当集群中的某个机器挂掉时,Zookeeper集群会自动进行故障检测和恢复。Zookeeper通过心跳机制来检测节点的健康状态,当发现某个节点不再发送心跳信号时,集群中的其他节点会认为该节点已经挂掉。然后,集群会从存活的节点中选举出新的领导者,并且重新分配故障节点上的数据副本,以保证系统的可用性和一致性。

5.ZK如何保证数据的一致性?

第一重新选取 leader 之后的数据同步;第二 leader 处理完事务请求后与 follower 保持数据同步。、

​ 首先是重新选举 leader 之后的数据同步,通过 FastleaderElection 选举算法选出 leader, 选出 leader 之后,leader 需与其他节点进行同步,同步完成 leader 才能真正变为 leader,当超过一半的 follower 和 leader 同步结束后才算完成同步,然后 follower 会带上自己最大的 zxid,尝试连接 leader,来确定数据是否同步。

​ 处理完事务请求的 leader 与 follwer 保持同步。事务请求全部由 leader 处理。当 leader 收到请求后,将请求事务转化为事务 proposal,由于 leader 会为每一个 follower 创建一个队列,将该事务放入响应队列,保证事务的顺序性。之后会由队列中顺序向其他节点广播该提案,follower 收到后会将其以事务的形式写入到本地日志中,并向 leader 发送反馈 ack,leader 会等待其他 follower 的回复,当收到一半以上 follower 响应时,leader 会向其他节点发送 commit 消息,同时 leader 提交该提案。当 follower 将数据同步完成之后,leader 会将该 follower 加入到真正可用的 follower 列表中。

为什么不适合还要用:成熟稳定,数据一致性,系统兼容,成本考虑,

1.简述ZAB协议?

​ ZAB 协议是为 Zookeeper 专门设计的一种支持崩溃恢复的消息广播协议。ZAB 协议只允许有一个主进程接受客户事务请求并处理,即 leader。当 leader 收到请求后,将请求事务转化为事务 proposal,由于 leader 会为每一个 follower 创建一个队列,将该事务放入响应队列,保证事务的顺序性。之后会在队列中顺序向其他节点广播该提案,follower 收到后会将其以事务的形式写入到本地日志中,并向 leader 发送反馈 ack 确认。leader 会等待其他 followe 的回复,当收到一半以上的 follower 响应时,leader 会向其他节点发送 commit 消息,同时提交该提案。

​ ZAB 有两种模式,分别为故障恢复模式以及消息广播。当系统启动或者 leader 服务器出现故障等现象时,进入故障恢复模式。将会开启新的一轮选举,选举产生的 leader 会与过半的 follower 进行同步,使数据一致。

​ 当同步结束后,退出恢复模式,进入消息广播模式。当一台遵从 ZAB 协议的服务器启动后,如果检测到有 leader 在广播消息,会自动进入恢复模式,当其完成与 leader 的同步之后,进入消息广播模式;如果集群中的非 leader 节点收到客户端请求,非 leader 节点会先将请求发送到 leader 服务器。

​ 故障恢复发时候,ZAB 协议两个需要保证的地方,第一就是 ZAB 协议需要保证已经被 leader 提交的事务最终被所有的机器提交;第二就是需要保证丢弃那些只在 leader 上提交的事务。为了保证以上两点,选举时如果选择 ZXID 最大的节点可以解决上述问题。

leader 重新选举的条件是当 leader 宕机或发生故障,集群中少于一半的节点与当前 leader 保持连接。

也就是说在zab会进行leader的选举,使用的fastleaderelection是paxos的实现

4.简述ZK的fastleaderelection选举leader的算法

刚启动和挂掉后

Zookeeper使用了一种称为Fast Leader Election的选举算法来选举集群中的领导者。在这个算法中,Zookeeper集群中的每个节点都有一个唯一的标识(ZXID),节点会将自己的ZXID与其他节点的ZXID进行比较,然后选出最大的ZXID作为领导者。如果有多个节点具有最大的ZXID,则会进一步比较它们的myid(节点ID),选出最大的myid作为领导者。通过这种方式,Zookeeper能够快速选举出一个新的领导者,并保证选举的一致性和正确性。选取ZXID最大的值,是为了保证被leader所提交的事务最终被所有的机器提交,保证丢弃那些只在leader上提交的事务。

Zab与PAXOS的联系与区别

Paxos算法的目的在于设计分布式的一致性状态机系统。

ZAB协议的设计目的在于分布式的高可用数据主备系统。

ZAB借鉴了Paxos算法,做了相应的改进,ZAB协议除了遵从Paxos算法中的读阶段和写阶段,还有加入了同步阶段

2.简述Paxos算法

​ paxos 算法是一种基于消息传递的且具有高度容错性的一种算法,解决的问题是一个分布式系统如何就某个值或者某个协议达成一致,该算法的前提是假设不存在拜占庭将军问题。

​ 在该算法中一共有三种角色:proposer, accpetor 和 learner。proposer 负责提出提案,acceptor 负责对该提案做出裁决,learner 负责学习得到的提案。为了避免单点故障,会有一个 acceptor 集合,proposer 向该集合发送提案,acceptor 集合中的每个成员都有可能同意该提案且每个 acceptor 只能批准一个提案,当有一半以上的成员同意,则同意该提案。

​ 它主要分为两个阶段:分别是 prepare 阶段和 accept 阶段。首先是 prepare 阶段,先由 proposer 提出编号为 Mn 的提案,向 accpetor 集合发送 prepare 请求。Accept 做出反馈:保证不会再接受编号比 Mn 小的提案;如果 acceptor 已经批准过某提案,会向 proposer 返回已经批准的编号最大的提案的 value 值。

​ 如果 acceptor 收到一个编号为 Mn 的请求且编号大于 accpetor 已经响应的所有 prepare 请求的编号,则它会将自己已经批准过的编号最大的提案值反馈给 proposer,同时 acceptor 承诺不会再接受编号比 Mn 小的提案。(优化:忽略编号小于已批准的提案的请求)。

​ 如果 proposer 收到了集合至少一半的响应,则会发送一个针对 Mn Vn 的 accept 请求给 Accpetor。Vn 为收到的所有响应中编号最大的提案的值。如果响应不包括值,则可以由 proposer 选择任意值。

然后就是 accpet 阶段,accpet 阶段是接受提案的要求。当 Acceptor 收到 accpet 请求后,只要未收到任何编号大于 Mn 的 prepare 请求,则通过该提案。

优化:为了避免死循环,比如两个 proposer 一次提出一系列编号递增的提案,可以产生一个主 proposer,提案只能由主 proposer 负责提出。

image-20240308101330672

RabbitMQ

有 4 个组件:生产者、Exchange、queue 队列、消费者。当生产者发出一条消息时,先经过 Exchange,由 Exchange 转发给队列,然后由消费者进行消费。

image-20240308104834156

为什么用到消息队列:

有发布者发布消息,直到有消费值消费这条信息,否侧会一直存在在队列中

负载均衡,可以被多个消费者同时消费,但每条信息只能被消费一次。

而异步或批量确认则允许一次确认多条消息,提高了效率。

rabbitmq实现了后台监控平台,可以在该平台上看到所有创建的队列的详细情况,良好的后台管理平台可以方便我们更好的使用;

队列,每条消息都可以选择性持久化,持久化粒度更小,更灵活;

项目rabbitmq的作用:削峰,异步,解耦,消息缓冲,消息分发

就是一个系统或者一个模块,调用了多个系统或者模块,互相之间的调用很复杂,维护起来很麻烦。有mq的话A系统产生一条数据,发送到mq,哪个系统需要数据自己去mq里面消费。通过mq,pub/sub发布订阅消息这个模型,A系统就与其他系统彻底解耦。

在下单的过程中会使用到,下单成功后会给用户发送一个消息,然后发送这个短信的接口,接口出现问题,或者对调用这个接口的运营商出现问题的话,那么我们就会被阻塞到,这个下单的流程就不完整,就导致下单不成功,所以用户提交订单时,网站可以将订单信息发送到rabbitmq中的订单队列中

还有就是削峰,按顺序处理,当大量用户涌入进来,如果不一条一条处理这些数据的话,无论我们系统还是短信运营商,都会承受不住,不利于我们的系统运行操作。

不使用RabbitMQ可能会导致系统在高并发处理、系统解耦、稳定性保障、可扩展性和维护成本方面面临挑战。这些挑战可能会影响系统的长期运行和发展

异步:

image-20240310110813760 image-20240310110857977

坏处

系统可用性降低:部署多个MQ实例,提供系统的容错能力,

复杂度提高:模块化设计,重试机制,监控和报警

  1. 消息可靠性方面。Kafka 不能保证消息的完全可靠,对数据丢失不敏感;而 RabbitMQ 则保证绝对可靠 (AMOP 特性)。
  2. 消息传递方面。Kafka 中生产者发出的消息被均匀分布到多个 part 中,broker 收到消息后写入 segment 文件,只能当 segment 的消息条数达到配置数或者消息发布时间超过阈值时,segment 上的消息才会被 flush 到磁盘,最终被消费者收到;而 Rabbit 通过交换机 (Exchange) 实时转发消息。
  3. RabbitMQ 适合处理数据量小,但得保证实时且高可靠的消息。而 Kafka 的具有较高的数据吞吐量。
  4. RabbitMQ 的服务生产者和消费者能力需对等,否则消息堆积影响性能。而 Kafka 大量依赖 Zookeeper,我们的除了要监控 Kafka 之外还得监控 Zookeeper。
  5. Kafka 比较轻量级,而 RabbitMQ 比较重。

**rabbitmq:重量级,高可靠,异步,不保证实时;**rabbitmq是一个专门的AMQP协议队列,他的优势就在于提供可靠的队列服务,并且可做到异步,而redis主要是用于缓存的,redis的发布订阅模块,可用于实现及时性,且可靠性低的功能。

1.生产者发送消息至MQ的数据丢失

解决方法:在生产者端开启comfirm 确认模式,你每次写的消息都会分配一个唯一的 id,

然后如果写入了 RabbitMQ 中,RabbitMQ 会给你回传一个 ack 消息,告诉你说这个消息 ok 了,但是需要生产者谨慎处理nack消息,以避免消息丢失

2.MQ收到消息,暂存内存中,还没消费,自己挂掉,数据会都丢失

解决方式:MQ设置为持久化。将内存数据持久化到磁盘中

3.消费者刚拿到消息,还没处理,挂掉了,MQ又以为消费者处理完

解决方式:用 RabbitMQ 提供的 ack 机制,简单来说,就是你必须关闭 RabbitMQ 的自动 ack,可以通过一个 api 来调用就行,然后每次你自己代码里确保处理完的时候,再在程序里 ack 一把。这样的话,如果你还没处理完,不就没有 ack 了?那 RabbitMQ 就认为你还没处理完,这个时候 RabbitMQ 会把这个消费分配给别的 consumer 去处理,消息是不会丢的。

image-20240309232022818

redis:

轻量级,低延迟,高并发,低可靠性;

redis:应用在缓存,在一些促销时,搜索中热数据的处理,比如将热门商品或在榜首的商品加载在redis中,不用去查询数据库,反应速度更快。

redis面试题https://mp.weixin.qq.com/s/aARg4Oftin6uYewAWGCsww

常见面试题

https://mp.weixin.qq.com/s/rFV1dVZHuRuVqv3cM0RD0w

五十道

https://mp.weixin.qq.com/s/pkGHXNCqGVbVofKwI2yP4A

为什么支持高并发

https://mp.weixin.qq.com/s/O-2w0jZ_T6ChBPXzjukQVQ

地图模块

微信商城部分,有很多商家,我们会调用百度地图的api,通过关键字获取这个城市内含有茶和茶叶的商家,将这些商家的地址按照我们需要的方式存储,比如我们需要地址,联系人,店名,然后渲染在页面。

第一步给运营部,市场部看这些数据,会打标签,问是否有意向问是否入住我们的店铺。有意向打上有意向,第二步洽谈成功的会成为我们b2b的客户,入住之后,当你加入公众号,点击周围商城的时候会将洽谈成功的客户显示在商场的入口

其余问题

1.预售订单和真实销售订单

预售订单不走库存,单纯记录一个字端在数据库后面再处理,他这个预售商品不能加入购物车直接支付定金,再购买的话减去差价,如果不这样处理则会出现超卖的问题,库存数据不准确,实际销售时,库存可能不够。

两个前端,页面和交互,四个后台,一个架构师,一个安卓,一个ios,2个测试

spring

https://mp.weixin.qq.com/s/8hwd0Ulr0BW7IUyWu4GgJw