精华内容
下载资源
问答
  • 前面篇讲过并发下单时进行优化的一些策略,后来我写了代码进行了实测。 关于redisson做分布式锁的代码在这篇文章。这里我来测试一下分布式锁的性能。 简单的controller package ...

    前面一篇讲过并发下单时进行优化的一些策略,后来我写了代码进行了实测。

    关于redisson做分布式锁的代码在这篇文章。这里我来测试一下分布式锁的性能。

    简单的controller

    package com.tianyalei.redislock.controller;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.annotation.Resource;
    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     * @author wuweifeng wrote on 2019-10-15.
     */
    @RequestMapping("/redisLock")
    @RestController
    public class IndexController {
        @Resource
        private IndexService indexService;
    
        private volatile AtomicInteger index = new AtomicInteger(Integer.MAX_VALUE);
    
    
        @RequestMapping("random")
        public String sellTwo(int count) {
            int i = index.getAndDecrement() % count;
            if (i == 0) {
                indexService.sell(0);
            } else if (i == 1) {
                indexService.sell(1);
            } else if (i == 2) {
                indexService.sell(2);
            } else if (i == 3) {
                indexService.sell(3);
            } else if (i == 4) {
                indexService.sell(4);
            }
    
            return "ok";
        }
    
        @RequestMapping("mm")
        public String sellmm(int count) {
            int i = index.getAndDecrement() % count;
            if (i == 0) {
                indexService.sellMemory(0);
            } else if (i == 1) {
                indexService.sellMemory(1);
            } else if (i == 2) {
                indexService.sellMemory(2);
            } else if (i == 3) {
                indexService.sellMemory(3);
            } else if (i == 4) {
                indexService.sellMemory(4);
            }
    
            return "ok";
        }
    }
    

    定义了2个接口,上面的是用redis分布式锁,下面的是走内存。

    package com.tianyalei.redislock.controller;
    
    import com.tianyalei.redislock.annotation.RedissonLock;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    import java.util.Random;
    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     * @author wuweifeng wrote on 2019-10-15.
     */
    @Service
    public class IndexService {
        @Resource
        private StringRedisTemplate stringRedisTemplate;
        private Logger logger = LoggerFactory.getLogger(getClass());
    
        private volatile AtomicInteger count1 = new AtomicInteger(500000);
        private volatile AtomicInteger count2 = new AtomicInteger(500000);
        private volatile AtomicInteger count3 = new AtomicInteger(500000);
        private volatile AtomicInteger count4 = new AtomicInteger(500000);
        private volatile AtomicInteger count5 = new AtomicInteger(500000);
    
    
        /**
         * 上分布式锁
         */
        @RedissonLock(lockIndex = 0)
        public void sell(Integer goodsId) {
            logger.info("goodId:" + goodsId);
            stringRedisTemplate.opsForValue().set(getRandomString(8), System.currentTimeMillis() + "abc");
            logger.info(System.currentTimeMillis() + "");
        }
    
        /**
         * 直接读内存
         */
        public void sellMemory(Integer goodsId) {
            logger.info("goodId:" + goodsId);
            switch (goodsId) {
                case 0:
                    logger.info("count1:" + count1.getAndDecrement());
                    break;
                case 2:
                    logger.info("count2:" + count2.getAndDecrement());
                    break;
                case 3:
                    logger.info("count3:" + count3.getAndDecrement());
                    break;
                case 4:
                    logger.info("count4:" + count4.getAndDecrement());
                    break;
                default:
                    logger.info("count5:" + count5.getAndDecrement());
                    break;
            }
    
            stringRedisTemplate.opsForValue().set(getRandomString(8), System.currentTimeMillis() + "abc");
            logger.info(System.currentTimeMillis() + "");
        }
    
        public static String getRandomString(int length) {
            String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            Random random = new Random();
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < length; i++) {
                int number = random.nextInt(62);
                sb.append(str.charAt(number));
            }
            return sb.toString();
        }
    }
    

    关于RedissonLock注解在前面的文章里写了代码了。

    sell方法就是针对goodsId进行加分布式锁,如果只有一个商品的话,就等于是完全在该商品的售卖上进行排队,性能就全靠redis的加锁解锁和业务耗时了。业务方面我采用直接将订单下到redis里的方式,不走数据库。正常情况下,业务耗时在10ms左右比较靠谱。

    sellMemory方法就是完全在内存中进行商品数量的减少,摆脱掉redis的网络通信。业务上也是将订单下到redis中。

    redis的一次加锁、解锁,我们可以计算它的耗时,加锁是一次通信,加锁失败后排队,然后等待redis的Channel监听回调,回调这又是一次通信,回调后再次去试图加锁并成功,这又是一次通信,业务上在redis里下一单,这又是一次通信。共计4次。

    那么在业务耗时相同的情况下,在内存中直接扣减库存会比通过redis分布式锁,少4次网络IO。

    结果如下:

    通过redis分布式锁下单

    200个线程并发,循环1次,购买1个商品,锁在同一个goodsId。共计600ms,200单下单完毕。

    200个线程并发,循环2次,购买1个商品,锁在同一个goodsId。共计1100ms,400单下单完毕。

    200个线程并发,循环2次,购买5个商品,锁在不同的goodsId,性能明显有所提升。共计600ms,400单下单完毕。

    400个线程并发,循环1次,购买5个商品,锁在不同的goodsId。共计600ms,400单下单完毕。

    400个线程并发,循环2次,购买5个商品,锁在不同的goodsId。共计1000ms,800单下单完毕。

    在内存里下单

    200个线程并发,循环1次,购买1个商品,锁在同一个goodsId。共计300ms,200单下单完毕。

    200个线程并发,循环2次,购买1个商品,锁在同一个goodsId。共计400ms,400单下单完毕。

    200个线程并发,循环1次,购买5个商品,锁在不同的goodsId。共计300ms,200单下单完毕。

    200个线程并发,循环2次,购买5个商品,锁在不同的goodsId。共计400ms,400单下单完毕。

    400个线程并发,循环1次,购买5个商品,锁在不同的goodsId。共计500ms,400单下单完毕。

    400个线程并发,循环2次,购买5个商品,锁在不同的goodsId。共计700ms,800单下单完毕。

    注意,这个测试是直接在HaProxy后面做的server,没有通过zuul网关。可以看到,在内存中下单,速度约是redis上锁的2倍。在并发高的情况下,差距会更大。

    当业务耗时更大的情况下,redis分布式锁在同一个商品上加锁,每秒大概能完成100单。而基于内存的话,单实例能下到1千单。

    基于内存,那么就需要通过分布式配置中心,在项目启动后,给商品数量count赋初值。譬如1万个商品,10个实例,则每个分配1千。

    实例之间彼此不会发生锁的冲突,基于cas的减库存,性能优异。

     

     

    展开全文
  • redis的qps

    千次阅读 2019-07-16 18:36:14
    1.单机的redis一般是支持上万甚至几万,具体的性能取决于数据操作的复杂性,如果仅仅是简单的kv操作的话,可以达到数万,如果是运行复杂的lua脚本的话,就可能只能到万左右 2.缓存一般是用来支撑读的高并发,一般...

    1.单机的redis一般是支持上万甚至几万,具体的性能取决于数据操作的复杂性,如果仅仅是简单的kv操作的话,可以达到数万,如果是运行复杂的lua脚本的话,就可能只能到一万左右
    2.缓存一般是用来支撑读的高并发,一般比较少用来支撑读的操作,一般读的操作是比较频繁的,甚至达到几万几十万,但是写的操作每秒才几千,这就需要读写分离了;
    架构一般做成主从架构:
    master:负责写数据,master数据写入之后,会将数据同步至slave中
    slave:负责读数据,多个slave
    这种的架构的有点在于可以水平扩容,比较灵活

    展开全文
  • 关于并发,QPS和TPS

    2020-05-18 14:34:36
    比如我们说1并发就是指1秒内有1000请求发送到web服务器。值得注意的是并发数和会话数是不同的,并发是一定会对服务器产生压力的,而会话数可能只是‘挂’在服务器上,并没有查询数据库等操作。比如我们说秒杀场景...

    并发

    有时候我们醉心于业务逻辑的书写,可能忽视了并发,这里来唠叨一下,如果错了请指正。
    在web开发中,并发指的是某个时间单位内对服务器产生的请求,一般指1秒内产生的请求。比如我们说1千并发就是指1秒内有1000请求发送到web服务器。并发数和会话数是不同的,并发是一定会对服务器产生压力的,而会话数可能只是‘挂’在服务器上,并没有查询数据库等操作。比如我们说秒杀场景并发高,是由于在那几秒内要完成下单,库存扣减等操作,这些操作会对服务器,数据库等产生巨大的压力。而要做一个大流量的静态页面则搞一台nginx服务器+CDN就足够了,因为这个场景很单纯,只是简单的页面输出,加上nginx这样优秀的开源软件和CDN后就变得很容易了。
    笔者理解:在web开发中,大部分的企业基本都没有十万以上并发量,更多的是几百几千的并发。所以没必要去跟风高并发,有那个时间还不如多去看看操作系统,刷刷算法呢。

    压测

    说到并发,一般就会说压测。我们开发好了接口后,要对接口进行压测,目的不是为了写报告,而是为了对接口承受能力有一个大概的了解。如果要达到更大的并发,我们也能通过压测去找出瓶颈,做对应的优化。
    压测工具有ab,jmeter,LoadRunner,以及云厂商的付费工具,比如阿里云的PTS性能测试。
    一般的压测流程是先用jmeter压测,达到并发要求后可以再用云厂商的工具进行压测。

    QPS

    说到压测,就会说QPS和TPS了。
    QPS指的服务器每秒响应的请求数,比如服务器部署了接口A,这个接口每秒能对500个请求作出正常响应,压测更大的量就会抛出504等错误时,我们就称接口A的QPS是500。

    TPS

    TPS的概念则复杂些,不过也有简化版:TPS指每秒内完成的事务数。
    这里的事务是指从请求服务器开始到服务器给出结果的过程。比如请求一个网页,从访问开始到页面输出结束,耗时1秒,则TPS是1。
    事务要怎么产生呢,需要用户去请求,所以我们再引入用户的概念。1个用户1秒内完成1笔事务,此时TPS是1。如果有1000个用户同时请求且都正常呢?则TPS是111000 = 1000。在jmeter工具中配置的线程数就是这里的用户数。
    那TPS和QPS的区别是什么?TPS是测试时我们自己去定义的,简单理解就是1个TPS包含1个或多个QPS。比如请求1个网页,网页在完成输出前会请求5个接口,则此时TPS是1,QPS是5。又比如我们把一次投票算做一个事务,这个投票包含获取投票数据和提交投票数据两个接口,则此时1TPS = 2QPS。再举个例子:把一次完整的游戏过程算做一个事物,这个过程需要登录,开始游戏,提交分数,抽奖,展示排行榜5个接口,则这里的1TPS = 5 QPS。

    RT

    RT是指接口的响应时间。

    RT Avg

    接口的平均响应时间。这个好比我们的人均收入,看看就好了。

    吞吐量

    没有一个单独的吞吐量参数,评估吞吐量时可以通过QPS,TPS,RT来评估。在jemter的聚合报告中有个Throughput参数可以参考。

    展开全文
  • 吞吐量(TPS)、QPS、并发数、响应时间(RT)概念 开发的原因,需要对吞吐量(TPS)、QPS、并发数、响应时间(RT)几个概念做下了解,查自百度百科...由于个系统通常会提供许多功能,而不同功能的处理逻辑也差...

    吞吐量(TPS)、QPS、并发数、响应时间(RT)概念

    开发的原因,需要对吞吐量(TPS)、QPS、并发数、响应时间(RT)几个概念做下了解,查自百度百科,记录如下:
    1. 响应时间(RT) 
      响应时间是指系统对请求作出响应的时间。直观上看,这个指标与人对软件性能的主观感受是非常一致的,因为它完整地记录了整个计算机系统处理请求的时间。由于一个系统通常会提供许多功能,而不同功能的处理逻辑也千差万别,因而不同功能的响应时间也不尽相同,甚至同一功能在不同输入数据的情况下响应时间也不相同。所以,在讨论一个系统的响应时间时,人们通常是指该系统所有功能的平均时间或者所有功能的最大响应时间。当然,往往也需要对每个或每组功能讨论其平均响应时间和最大响应时间。 
      对于单机的没有并发操作的应用系统而言,人们普遍认为响应时间是一个合理且准确的性能指标。需要指出的是,响应时间的绝对值并不能直接反映软件的性能的高低,软件性能的高低实际上取决于用户对该响应时间的接受程度。对于一个游戏软件来说,响应时间小于100毫秒应该是不错的,响应时间在1秒左右可能属于勉强可以接受,如果响应时间达到3秒就完全难以接受了。而对于编译系统来说,完整编译一个较大规模软件的源代码可能需要几十分钟甚至更长时间,但这些响应时间对于用户来说都是可以接受的。 

    2. 吞吐量(Throughput) 
         吞吐量是指系统在单位时间内处理请求的数量。对于无并发的应用系统而言,吞吐量与响应时间成严格的反比关系,实际上此时吞吐量就是响应时间的倒数。前面已经说过,对于单用户的系统,响应时间(或者系统响应时间和应用延迟时间)可以很好地度量系统的性能,但对于并发系统,通常需要用吞吐量作为性能指标。 
      对于一个多用户的系统,如果只有一个用户使用时系统的平均响应时间是t,当有你n个用户使用时,每个用户看到的响应时间通常并不是n×t,而往往比n×t小很多(当然,在某些特殊情况下也可能比n×t大,甚至大很多)。这是因为处理每个请求需要用到很多资源,由于每个请求的处理过程中有许多不走难以并发执行,这导致在具体的一个时间点,所占资源往往并不多。也就是说在处理单个请求时,在每个时间点都可能有许多资源被闲置,当处理多个请求时,如果资源配置合理,每个用户看到的平均响应时间并不随用户数的增加而线性增加。实际上,不同系统的平均响应时间随用户数增加而增长的速度也不大相同,这也是采用吞吐量来度量并发系统的性能的主要原因。一般而言,吞吐量是一个比较通用的指标,两个具有不同用户数和用户使用模式的系统,如果其最大吞吐量基本一致,则可以判断两个系统的处理能力基本一致。 

    3. 并发用户数 
      并发用户数是指系统可以同时承载的正常使用系统功能的用户的数量。与吞吐量相比,并发用户数是一个更直观但也更笼统的性能指标。实际上,并发用户数是一个非常不准确的指标,因为用户不同的使用模式会导致不同用户在单位时间发出不同数量的请求。一网站系统为例,假设用户只有注册后才能使用,但注册用户并不是每时每刻都在使用该网站,因此具体一个时刻只有部分注册用户同时在线,在线用户就在浏览网站时会花很多时间阅读网站上的信息,因而具体一个时刻只有部分在线用户同时向系统发出请求。这样,对于网站系统我们会有三个关于用户数的统计数字:注册用户数、在线用户数和同时发请求用户数。由于注册用户可能长时间不登陆网站,使用注册用户数作为性能指标会造成很大的误差。而在线用户数和同事发请求用户数都可以作为性能指标。相比而言,以在线用户作为性能指标更直观些,而以同时发请求用户数作为性能指标更准确些。 
    4. QPS每秒查询率(Query Per Second) 
      每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,在因特网上,作为域名系统服务器的机器的性能经常用每秒查询率来衡量。对应fetches/sec,即每秒的响应请求数,也即是最大吞吐能力。 (看来是类似于TPS,只是应用于特定场景的吞吐量)

    展开全文
  • 首先对吞吐量()、QPS、并发数、响应时间(RT)几个概念一直比较模糊,也不知道哪些指标可以较好的衡量系统的性能。今天特意查了些资料做一些记录:...由于个系统通常会提供许多功能,而不同功能的处理逻辑也...
  • 吞吐量(TPS)、QPS、并发数、响应时间(RT)概念 开发的原因,需要对吞吐量(TPS)、QPS、并发数、响应时间(RT)几个概念做下了解,查自百度百科...由于个系统通常会提供许多功能,而不同功能的处理逻辑也差...
  • 1.redis不能支撑高并发的瓶颈在哪里? 单机 2、如果redis要支撑超过10万+的并发,那...读写分离,一般来说,对缓存,一般都是用来支撑读高并发的,写的请求是比较少的,可能写请求也就一秒钟几 大量的请...
  • Redis号称可以支撑10w+qps,当然这也给机器配置有一定的关系,如果单实例满足不了需求,想追求更高的性能和稳定性,可以选择主从、哨兵已经更好的解决方案Redis-Cluster 集群。 8-22 投递简历 8-24 一面(大概1...
  • 目前斗鱼直播系统每天有20亿+的请求量,并且在今年3月份,PDD入驻斗鱼的时候还曾达到40万+的瞬时QPS,同时我们的服务增长到了上实例的规模,在全国不同地区和不同机房进行了部署,提供给上百个内部业务方使用。...
  • 题目: 设计个系统处理词语搭配问题,比如说 中国 和人民可以搭配, 则中国人民 人民中国都有效。要求:  *系统每秒的查询数量...性能要求:每秒查询量达到上次,意思就是QPS要达到1000以上。 搜索端使用
  • 公司内部有套RPC服务框架,java开发的,rpc协议用的redis我所在的部门没java人手,但夸部门的数据交互又越来越多,开始用http 接口性能不好,qps到2-3的时候调用方经常发生各种curl 网络错误,导致拿不到数据...
  • 我们团队负责的广告系统承接了比较大的C端流量,平峰期间的请求量基本达到了上千QPS,过去也遇到了很多次GC相关的线上问题。 这篇文章,我再分享个更棘手的Young GC耗时过长的线上案例,同时会整理下YGC相关的知识...
  • Redis号称可以支撑10w+qps,当然这也给机器配置有一定的关系,如果单实例满足不了需求,想追求更高的性能和稳定性,可以选择主从、哨兵已经更好的解决方案Redis-Cluster 集群。 MySQL为何不选择平衡二叉树 既然...
  • 我们团队负责的广告系统承接了比较大的C端流量,平峰期间的请求量基本达到了上千QPS,过去也遇到了很多次GC相关的线上问题。 这篇文章,我再分享个更棘手的Young GC耗时过长的线上案例,同时会整理下YGC相关的...
  • 次mySQL慢sql优化

    2021-03-25 11:53:06
    查看duubo服务,发现qps达到了8多,线程池爆满,mysql的cpu达到100%。 是不是某个业务线刚刚上线疯狂调用服务导致?询问过后发现并没有。之前监控过详情页处理某个业务的接口,逻辑复杂,查询缓慢...
  • Redis号称可以支撑10w+qps,当然这也给机器配置有一定的关系,如果单实例满足不了需求,想追求更高的性能和稳定性,可以选择主从、哨兵已经更好的解决方案Redis-Cluster 集群。 为什么学Java?Java能干什么? ...
  • 我们团队负责的广告系统承接了比较大的C端流量,平峰期间的请求量基本达到了上千QPS,过去也遇到了很多次GC相关的线上问题。 这篇文章,我再分享个更棘手的Young GC耗时过长的线上案例,同时会整理下YGC相关的知识...
  • 楼主当时有点绝望,因为跟我们其他的服务上qps差距太大了,但是考虑到这个服务的特殊性,所以没有仔细去验证性能这么差的原因在哪儿。 上线1月多,其实没有遇到过该服务出现并发特别大导致服务不可用,所以也还...
  • Redis号称可以支撑10w+qps,当然这也给机器配置有一定的关系,如果单实例满足不了需求,想追求更高的性能和稳定性,可以选择主从、哨兵已经更好的解决方案Redis-Cluster 集群。 Redis 什么是Redis? Redis的...
  • MySQL 单实例,读写 QPS 通常只有级别(3000~6000),经过优化的查询语句,在性能较好的机器上,读 QPS可接近 1w。 MySQL 执行次普通的查询或者修改操作,平均耗时在 10~100ms 级别。 慢查询:针对用户端的...
  • RockeMQ笔记

    2020-06-14 16:39:30
    这个些MQ在同等机器条件下,能抗多少QPS(每秒能抗几千QPS,还是几万QPSQPS:每秒查询率) 4.性能如何(发 条消息要2ms还是20ms) 5.可靠性能不能得到保障(MQ部署的服务器挂掉怎么办) RocketMQ: 1.开发语言...
  • 当系统的用户量上来,每秒QPS后,可能就会导致系统的各种卡顿,超时等情况,这时优化操作不可避免 1.2. 优化步骤 第步:优化大SQL,对于多表关联的SQL,当单表数据几百上千万行时,执行可能会达到好几秒,对...
  • python 转 go

    2019-10-08 14:09:06
    最开始我们的业务架构是 ...转的原因:后面来了个业务需求,对 api 的响应速度和 qps 都有要求,基本上是几 qps 每秒。因为本身的业务逻辑比较简单,所以我们 profiling 了下,发现瓶颈在 Python 本身。我以前用...
  • 这些MQ在同等机器条件下,能抗多少QPS(每秒抗几千QPS还是几万QPS)? 性能有多高(发送条消息给他要2ms还是20ms)? 可用性能不能得到保证(要是MQ部署的机器挂了怎么办)? 2.深层次的考量 他们会不会丢数据...
  • 1、redis高并发跟整个系统的高并发之间的关系 redis,你要搞高并发的话,不可避免,要把底层...读写分离,一般来说,对缓存,一般都是用来支撑读高并发的,写的请求是比较少的,可能写请求也就一秒钟几 ...
  • 无锁并发编程简谈

    2018-05-10 11:56:04
    (有半年没有写博客了,时间飞逝呀。。。。 :o ) 这里简单介绍一下无锁并发编程。...)如果并发不太大,qps是数百时,这些方法还没有问题,但是当qps增加到数时,这些同步方法的开销就太大...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 144
精华内容 57
关键字:

qps一千