红包雨项目复盘

红包雨项目复盘

prd评审  

    prd评审我没参加,有的地方还是没做到:比如现在的项目意义在哪里?跟以前的业务有什么关联?具体关联的是什么? 以前的业务是什么? 现在要怎么做?
    
    和以前的业务关系没搞清楚,可能就会出现,后面产品来问,发放红包的逻辑怎么怎么样?有没有走以前的限制逻辑?虽然我怼回去了,但是prd评审卡主了,就不会出现后续的分歧
    
    这里可以确定的是,发放红包时,不能有限制规则。原因:用户领了红包,你给用户说这个红包限制了,不能领。这样肯定不行,有点像人家都把裤子脱了,你给人家看这个。。。
    如果实在要限制,就是在配置的时候,不能配置有限制规则的红包。
    

技术

这次红包雨项目,是一次拉客营销活动项目,是app端的活动,流量可能比以前要大很多。

所以app端下来的请求,采用缓存redis + 消息中间件rabbitmq  后台采用mysql

redis 客户端用的是 spring-boot 的 RedisTemplate

因为大家都在领红包嘛,当然红包总量是共享资源  
需要分布式锁 ——————这里用的是以前的一个注解@Lock(value = RedisLockKey.RP_ACT_RAIN_LOCK_KEY, timeout = 10),还没太弄明白怎么实现的

因为要操作很多相关的key,采用了redis事务来保证相关的操作都执行。保证数据一致性。
获取锁应该阻塞,怎么样才能优雅一点。有没有阻塞队列啥的。公平锁还是非公平锁。等等。 有空了自己实现一个。

活动配置,有批量放入缓存的操作用了Pipeline

这次redis遇到了序列化的问题

场景是这样子的:后台配置程序,配置活动的时候,将配置信息写入缓存。前台app程序从缓存读取。这个流程中,存储对象不行。
1、默认的redis序列化工具,序列化时,带上了对象的type,就是对象的全限定名。在接收方肯定没有相同的对象名,来接收数据。所以就不行。
解决办法:从写序列化工具,用json格式来传送数据。不要类型。


2、RedisTemplate客户端,用increment添加的数据也是字符串的。要获取数据不能用get方法,会报错。只能用 increment 0 来获取数据。这应该是RedisTemplate的bug

总的来说因为序列化和RedisTemplate客户端 导致数据类型混乱,各种报错。很头痛。


rabbitmq 高可用数据最终一致性
这里用的原始的客户端 channel。需要研究一下spring的客户端。

首先要producer这边需要确保和borker的通信可靠。
我使用了下面的方法来保证可靠
首先在方法上添加注解@Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000L, multiplier = 2))

方法内代码如下
channel.exchangeDeclare(exchange, "direct");
            channel.confirmSelect();
            channel.basicPublish(exchange, ROUTING_KEY, true, null, (msg).getBytes(StandardCharsets.UTF_8));
            channel.addConfirmListener(new ConfirmListener() {
                @Override
                public void handleAck(long deliveryTag, boolean multiple) throws IOException {
                    logger.info("红包雨消息发送成功 {}", msg);
                }

                @Override
                public void handleNack(long deliveryTag, boolean multiple) throws IOException {
                    sendMessageMq(msg);
                }
            });

不过  channel.addConfirmListener(new ConfirmListener() { 这句没生效,我从来没收到过 确认消息。是不是跟broker的配置有关系。。 需要进一步研究。

其次是consumer保证消息收到,而且要防止各种原因导致的消息重复接收(就是大家经常提到的幂等,这里是用数据加时间戳来处理的)。

用消息确认来保证消息一定收到

rpRainOpenRedpacketHandler.handleOpenRedpacket(msg);
channel.basicAck(envelope.getDeliveryTag(), false);

 

可以优化的点:

1、缓存失效,需要查询数据库。避免失效时遇到大量流量查询mysql,导致mysql的负载变高。

    解决:线程同步+两次校验  就是单利的模式(保证缓存失效的时候,只有一个线程访问数据库,避免大量流量给数据造成压力)

2、如果量大的话,可以多搞几个消息消费方增加消费速度。这个也要看数据库的能力。

 

 

事务的问题
1、事务的传播特性

2、分布式事务不确定能保证。redis数据源,mysql数据源

3、@Transactional 

 

先写到这里,后续不断完善总结。    


  总结

一个比较正常的,如果接的有意的项目,一定要总结。总结才能积累。

 

 

  
    


 

你可能感兴趣的:(项目技术)