用redis处理并发写的工作总结

阅读更多

     公司运营部那边需要做一个营销活动-springrain活动,上午和team leader、同一组的同事和产品经理一同听取并讨论了活动的需求,以及一些细节性的东西。

      大致需求是这样的,由于保密的原因,这里只列出大概的需求。就是每一个阶段都有一个浇水的滴数,达到这个浇水的滴数,app上的小数就成长一个阶段,以此类推。一共有5个阶段。

      后面我和同事就开始进行数据库表的相关设计,以及涉及到提供给app前端的接口方法。这是每一次做后端接口的必要的工作步骤。api的接口方法,我和另一个同事进行了不同的分工,每人写几个接口方法,同时进行自测并和前端人员进行联调。

      在设计到给树浇水的这个接口的时候,同事一开始是对于每一个浇水的人,都直接进行数据库操作,保存每一个会员的浇水记录,接口很快就写完并发布了。后续进行测试的时候,发现了问题。同事写了一个python的脚本进行多线程并发去测试该接口,出来的结果出人意料的出错了,有丢失更新的问题。或者说是并发导致了数据被覆盖了。所以,对于存在并发的这种操作,我们想到的方法就是加锁,或者同步。

     加锁,这种操作我们一般分为业务加锁和数据库层面的锁。数据库层面的锁我们可以用悲观锁也可以用乐观锁,但通常这种问题我们不会再数据库层面进行处理。所以这种解决方案我们就忽略到,有对悲观锁和乐观锁不明白的童鞋,请自行google。

   这里我们说一下业务层面的加锁也就是通常的同步操作,对于java层面的同步一般对于并发的性能支持的不好,如果并发量比较大,会造成排队甚至丢失连接的情况。所以这种方案对于我们也不可行。最后讨论的结果是使用基于生产者-消费者的模式解决并发问题,是并发从并发变为同步操作,从多线程变单线程。

这里我只写一下伪代码:

public void save(){

      //组织数据
     //将数据放入到队列,返回
     jedisClient.lpop(xxxx)
}

 

    然后启动一个后台线程池从队列中取出需要保存的数据对象,进行数据库操作。类型的伪代码如下:

ScheduledExecutorService executor = Executors.newFixedThreadPool(6);
executorService.execute(new Runnable() {
            @Override
            public void run() {
              //数据库操作
       
            }
}

 从而解决上面的问题,这里面的队列是redis内部实现的一个简单的队列

你可能感兴趣的:(用redis处理并发写的工作总结)