被面试官问到项目中的难点?是时候对自己的项目进行总结了(记一次项目问题总结)

项目介绍

此项目提供了小组成员共享任务提醒的功能。

具体功能为:

  • 管理员对任务或事件的创建,以及对任务的分配。

  • 定时给任务执行人发送提醒。

  • 任务执行人完成任务。

额外说明:

  • 小组中最少有一个管理员,最多有两个管理员。
  • 成员数量不做限制,但根据场景不建议超过10个。
  • 除管理员外普通成员没有创建和修改任务的权限。
  • 任务:固定时间点给执行人提醒要做的事情。
  • 事件:所有成员都可以看到的有时间段的事件,事件本身不具备提醒功能,可以添加关联的任务给相应的执行人发送提醒,比如在事件开始的时候关联一个事件开始的任务,在事件结束的时候关联事件结束的任务,事件创建时可以选择是否同步创建关联任务,任务创建时可以选择是否关联已存在的事件。

1、设计任务和事件的规则计算及存储方式

设计方案

  1. 首先pass掉子任务全量落表的方式(无限重复规则的按时间落表往后半年或1年的数据),此方式对数据库的压力太大。

  2. 采用存储任务规则的方式,对已经发生的任务落历史表,未发生的任务使用规则计算发生时间,未发生已修改的存特殊(special)表。

问题

  1. 开发时间成本问题: 任务规则引擎设计,人力成本及时间成本太大。

  2. 计算性能问题: 考虑到规则解析计算的性能可能会出现瓶颈,提出此问题。

解决方案:

  1. 使用rfc-2445标准规范,选用开源项目组件。寻找可靠的开源组件并测试其性能表现,最终经过Jmeter压力测试发现其性能瓶颈出现在http的并发请求上,规则计算不是其性能瓶颈,为减少网络开销,最终对接口进行封装,采用一次请求计算多条规则的方式设计接口。

  2. 对入口服务的接口采用redis缓存进一步缓解服务器压力,对常用接口的结果进行缓存,如首页的接口,由于其参数一天才变动一次,所以完全可采用缓存的方式存储数据。

2、分布式事务解决方案

问题

微服务架构的系统中总会出现分布式事务的问题,例如:任务服务和事件服务为两个单独的服务,而任务与事件又有关联的操作,修改一条事件需要修改所有与此事件关联的任务,这就涉及到数据的一致性了,需要使用分布式事务来解决问题。

解决方式

解决分布式事务有很多方法,例如:基于可靠消息的最终一致性方案、TCC事务补偿型方案、最大努力通知型。

经过讨论,最终选用了最大努力通知型。详细设计方案为:调用对方服务时,判断是否成功,成功则流程继续,失败就把调用信息存入重试表中,然后继续下面的流程。最后使用定时扫描的方式重新发起接口的调用,重试调用一定次数,如果成功则结束,如果一直未成功则通知管理员处理此信息。

3、数据库与redis缓存的数据一致性

问题

在使用了缓存的业务场景中,例如查询用户的可访问资源,在修改数据库中的这些数据时,可能导致用户查出的缓存数据还是旧数据。

解决方式

设置redis缓存数据过期时间,修改数据时清除对应的缓存,使用户下次查询直接使用数据库的数据。

4、缓存穿透

问题

恶意用户发起攻击,查询一个缓存和数据库中都不存在的数据,造成一直查询数据库导致数据库压力飙升甚至垮掉。

解决方案

1) 接口增加用户权限校验,id做校验,例如 id<0 的直接拦截。

2) 在数据库中取不到的数据存一个空值到Redis,设置缓存有效时间较短,例如30秒后过期。

3) 使用布隆过滤器,布隆过滤器可以做到的效果:一个一定不存在的数据会被拦截掉,可能存在的数据才会去查数据库。因为这个特性,只要设置合理的参数就可以极大的缓解缓存穿透问题。

了解更多:缓存穿透、缓存击穿、缓存雪崩区别和解决方案

5、分布式锁

问题

本系统功能允许一个家庭组中存在多名管理员,所以存在多名管理员同时操作一条数据的可能性,为保证数据的一致性,需要对操作进行加锁处理,微服务中每个服务可能有多个实例,所以存在多个进程的线程操作同一条数据的情况,于是普通单机系统的应用使用的java内存锁不再可靠。

解决方案

分布式锁提供了分布式系统中跨JVM的互斥机制的实现,常用的分布式锁的实现方式有三种:

1、基于数据库实现分布式锁

2、基于缓存(Reids等)实现分布式锁

3、基于Zookeeper实现分布式锁

其中基于数据库的分布式锁实现方式最为简单,但是太过依赖数据库。Redis和Zookeeper中,因为Redis已在本系统中有集成,而且实现起来简单,只要注意Redis实现分布式锁的方式中的几个问题就能做出来一个相对完善的方案。PS:SpringBoot中使用Redis实现分布式锁

6、消息的延迟推送

问题

系统中一条消息推送给客户之后,如果客户没有及时处理需要在间隔一段时间后再发送一次。

解决方案

使用RabbitMQ的死信队列实现消息的延迟发送,其实现方式是设置第一个队列的消息存活时间(TTL),此队列不设置消费者,配置交换机,将过期的消息交换(死信交换DLX)到另一个队列,消费者消费此队列,此时距离消息产生就已经过了一段时间,实现了消息的延迟推送。PS:RabbitMQ的死信队列实现消息的延时消费

  • 18
    点赞
  • 172
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值