精华内容
下载资源
问答
  • java高并发测试代码,只要你机器扛得住
    千次阅读
    2018-12-27 11:25:25
    package com.example.test;
    
    import java.net.URL;
    import java.net.URLConnection;
    import java.util.concurrent.CountDownLatch;
    
    /**
     * Created with IDEA
     * author:QinWei
     * Date:2018/12/27
     * Time:11:08
     * 并发测试
     */
    public class ConnectTest {
    
        public static void main(String[] args) {
            int count=1000000;
            final CountDownLatch cdl=new CountDownLatch(count);
            for (int i = 0; i < count; i++) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        cdl.countDown();
                        try {
                            cdl.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        try {
                            connect();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
    
        }
    
            public static void connect() throws Exception {
                final String urlStr="https://blog.52itstyle.com/";
                URL url=new URL(urlStr);
                URLConnection urlConnection = url.openConnection();
                urlConnection.setDoInput(true);
                urlConnection.setDoOutput(true);
                urlConnection.connect();
                System.out.println(urlConnection.getInputStream());
        }
    }
    

     

    更多相关内容
  • 图书目录:第1章 走入并行世界 11.1 何去何从的并行计算 11.1.1 忘掉那该死的并行 21.1.2 可怕的现实:摩尔定律的失效 41.1.3 柳暗花明:不断地前进 ...71.2.2 并发(Concurrency)和并行(Parallelism) 81.2....

    图书目录:

    第1章 走入并行世界 1

    1.1 何去何从的并行计算 1

    1.1.1 忘掉那该死的并行 2

    1.1.2 可怕的现实:摩尔定律的失效 4

    1.1.3 柳暗花明:不断地前进 5

    1.1.4 光明或是黑暗 6

    1.2 你必须知道的几个概念 7

    1.2.1 同步(Synchronous)和异步(Asynchronous) 7

    1.2.2 并发(Concurrency)和并行(Parallelism) 8

    1.2.3 临界区 9

    1.2.4 阻塞(Blocking)和非阻塞(Non-Blocking) 9

    1.2.5 死锁(Deadlock)、饥饿(Starvation)和活锁(Livelock) 10

    1.3 并发级别 11

    1.3.1 阻塞 11

    1.3.2 无饥饿(Starvation-Free) 11

    1.3.3 无障碍(Obstruction-Free) 12

    1.3.4 无锁(Lock-Free) 13

    1.3.5 无等待(Wait-Free) 13

    1.4 有关并行的两个重要定律 14

    1.4.1 Amdahl定律 14

    1.4.2 Gustafson定律 16

    1.4.3 是否相互矛盾 17

    1.5 回到Java:JMM 18

    1.5.1 原子性(Atomicity) 18

    1.5.2 可见性(Visibility) 20

    1.5.3 有序性(Ordering) 22

    1.5.4 哪些指令不能重排:Happen-Before规则 27

    第2章 Java并行程序基础 29

    2.1 有关线程你必须知道的事 29

    2.2 初始线程:线程的基本操作 32

    2.2.1 新建线程 32

    2.2.2 终止线程 34

    2.2.3 线程中断 38

    2.2.4 等待(wait)和通知(notify) 41

    2.2.5 挂起(suspend)和继续执行(resume)线程 45

    2.2.6 等待线程结束(join)和谦让(yeild) 49

    2.3 volatile与Java内存模型(JMM) 50

    2.4 分门别类的管理:线程组 53

    2.5 驻守后台:守护线程(Daemon) 54

    2.6 先做重要的事:线程优先级 56

    2.7 线程安全的概念与关键字synchronized 57

    2.8 程序中的幽灵:隐蔽的错误 61

    2.8.1 无提示的错误案例 62

    2.8.2 并发下的ArrayList 63

    2.8.3 并发下诡异的HashMap 64

    2.8.4 初学者常见的问题:错误的加锁 67

    第3章 JDK并发包 71

    3.1 多线程的团队协作:同步控制 71

    3.1.1 关键字synchronized的功能扩展:重入锁 72

    3.1.2 重入锁的好搭档:Condition 81

    3.1.3 允许多个线程同时访问:信号量(Semaphore) 85

    3.1.4 ReadWriteLock读写锁 86

    3.1.5 倒计数器:CountDownLatch 89

    3.1.6 循环栅栏:CyclicBarrier 91

    3.1.7 线程阻塞工具类:LockSupport 94

    3.1.8 Guava和RateLimiter限流 98

    3.2 线程复用:线程池 101

    3.2.1 什么是线程池 102

    3.2.2 不要重复发明轮子:JDK对线程池的支持 102

    3.2.3 刨根究底:核心线程池的内部实现 108

    3.2.4 超负载了怎么办:拒绝策略 112

    3.2.5 自定义线程创建:ThreadFactory 115

    3.2.6 我的应用我做主:扩展线程池 116

    3.2.7 合理的选择:优化线程池线程数量 119

    3.2.8 堆栈去哪里了:在线程池中寻找堆栈 120

    3.2.9 分而治之:Fork/Join框架 124

    3.2.10 Guava中对线程池的扩展 128

    3.3 不要重复发明轮子:JDK的并发容器 130

    3.3.1 超好用的工具类:并发集合简介 130

    3.3.2 线程安全的HashMap 131

    3.3.3 有关List的线程安全 132

    3.3.4 高效读写的队列:深度剖析ConcurrentLinkedQueue类 132

    3.3.5 高效读取:不变模式下的CopyOnWriteArrayList类 138

    3.3.6 数据共享通道:BlockingQueue 139

    3.3.7 随机数据结构:跳表(SkipList) 144

    3.4 使用JMH进行性能测试 146

    3.4.1 什么是JMH 147

    3.4.2 Hello JMH 147

    3.4.3 JMH的基本概念和配置 150

    3.4.4 理解JMH中的Mode 151

    3.4.5 理解JMH中的State 153

    3.4.6 有关性能的一些思考 154

    3.4.7 CopyOnWriteArrayList类与ConcurrentLinkedQueue类 157

    第4章 锁的优化及注意事项 161

    4.1 有助于提高锁性能的几点建议 162

    4.1.1 减少锁持有时间 162

    4.1.2 减小锁粒度 163

    4.1.3 用读写分离锁来替换独占锁 165

    4.1.4 锁分离 165

    4.1.5 锁粗化 168

    4.2 Java虚拟机对锁优化所做的努力 169

    4.2.1 锁偏向 169

    4.2.2 轻量级锁 169

    4.2.3 自旋锁 170

    4.2.4 锁消除 170

    4.3 人手一支笔:ThreadLocal 171

    4.3.1 ThreadLocal的简单使用 171

    4.3.2 ThreadLocal的实现原理 173

    4.3.3 对性能有何帮助 179

    4.4 无锁 182

    4.4.1 与众不同的并发策略:比较交换 182

    4.4.2 无锁的线程安全整数:AtomicInteger 183

    4.4.3 Java中的指针:Unsafe类 185

    4.4.4 无锁的对象引用:AtomicReference 187

    4.4.5 带有时间戳的对象引用:AtomicStampedReference 190

    4.4.6 数组也能无锁:AtomicIntegerArray 193

    4.4.7 让普通变量也享受原子操作:AtomicIntegerFieldUpdater 194

    4.4.8 挑战无锁算法:无锁的Vector实现 196

    4.4.9 让线程之间互相帮助:细看SynchronousQueue的实现 201

    4.5 有关死锁的问题 205

    第5章 并行模式与算法 209

    5.1 探讨单例模式 209

    5.2 不变模式 213

    5.3 生产者-消费者模式 215

    5.4 高性能的生产者-消费者模式:无锁的实现 220

    5.4.1 无锁的缓存框架:Disruptor 221

    5.4.2 用Disruptor框架实现生产者-消费者模式的案例 222

    5.4.3 提高消费者的响应时间:选择合适的策略 225

    5.4.4 CPU Cache的优化:解决伪共享问题 226

    5.5 Future模式 230

    5.5.1 Future模式的主要角色 232

    5.5.2 Future模式的简单实现 233

    5.5.3 JDK中的Future模式 236

    5.5.4 Guava对Future模式的支持 238

    5.6 并行流水线 240

    5.7 并行搜索 244

    5.8 并行排序 246

    5.8.1 分离数据相关性:奇偶交换排序 246

    5.8.2 改进的插入排序:希尔排序 250

    5.9 并行算法:矩阵乘法 254

    5.10 准备好了再通知我:网络NIO 258

    5.10.1 基于Socket的服务端多线程模式 259

    5.10.2 使用NIO进行网络编程 264

    5.10.3 使用NIO来实现客户端 272

    5.11 读完了再通知我:AIO 274

    5.11.1 AIO EchoServer的实现 275

    5.11.2 AIO Echo客户端的实现 277

    第6章 Java 8/9/10与并发 281

    6.1 Java 8的函数式编程简介 281

    6.1.1 函数作为一等公民 282

    6.1.2 无副作用 283

    6.1.3 声明式的(Declarative) 283

    6.1.4 不变的对象 284

    6.1.5 易于并行 284

    6.1.6 更少的代码 284

    6.2 函数式编程基础 285

    6.2.1 FunctionalInterface注释 285

    6.2.2 接口默认方法 286

    6.2.3 lambda表达式 290

    6.2.4 方法引用 291

    6.3 一步一步走入函数式编程 293

    6.4 并行流与并行排序 298

    6.4.1 使用并行流过滤数据 298

    6.4.2 从集合得到并行流 299

    6.4.3 并行排序 299

    6.5 增强的Future:CompletableFuture 300

    6.5.1 完成了就通知我 300

    6.5.2 异步执行任务 301

    6.5.3 流式调用 303

    6.5.4 CompletableFuture中的异常处理 303

    6.5.5 组合多个CompletableFuture 304

    6.5.6 支持timeout的 CompletableFuture 306

    6.6 读写锁的改进:StampedLock 306

    6.6.1 StampedLock使用示例 307

    6.6.2 StampedLock的小陷阱 308

    6.6.3 有关StampedLock的实现思想 310

    6.7 原子类的增强 313

    6.7.1 更快的原子类:LongAdder 314

    6.7.2 LongAdder功能的增强版:LongAccumulator 320

    6.8 ConcurrentHashMap的增强 321

    6.8.1 foreach操作 321

    6.8.2 reduce操作 321

    6.8.3 条件插入 322

    6.8.4 search操作 323

    6.8.5 其他新方法 324

    6.9 发布和订阅模式 324

    6.9.1 简单的发布订阅例子 326

    6.9.2 数据处理链 328

    第7章 使用Akka构建高并发程序 331

    7.1 新并发模型:Actor 332

    7.2 Akka之Hello World 332

    7.3 有关消息投递的一些说明 336

    7.4 Actor的生命周期 337

    7.5 监督策略 341

    7.6 选择Actor 346

    7.7 消息收件箱(Inbox) 346

    7.8 消息路由 348

    7.9 Actor的内置状态转换 351

    7.10 询问模式:Actor中的Future 354

    7.11 多个Actor同时修改数据:Agent 356

    7.12 像数据库一样操作内存数据:软件事务内存 359

    7.13 一个有趣的例子:并发粒子群的实现 363

    7.13.1 什么是粒子群算法 364

    7.13.2 粒子群算法的计算过程 364

    7.13.3 粒子群算法能做什么 366

    7.13.4 使用Akka实现粒子群 367

    第8章 并行程序调试 375

    8.1 准备实验样本 375

    8.2 正式起航 376

    8.3 挂起整个虚拟机 379

    8.4 调试进入ArrayList内部 380

    第9章 多线程优化示例—Jetty核心代码分析 385

    9.1 Jetty简介与架构 385

    9.2 Jetty服务器初始化 387

    9.2.1 初始化线程池 387

    9.2.2 初始化ScheduledExecutorScheduler 389

    9.2.3 初始化ByteBufferPool 390

    9.2.4 维护ConnectionFactory 393

    9.2.5 计算ServerConnector的线程数量 394

    9.3 启动Jetty服务器 394

    9.3.1 设置启动状态 394

    9.3.2 注册ShutdownMonitor 395

    9.3.3 计算系统的线程数量 395

    9.3.4 启动QueuedThreadPool 396

    9.3.5 启动Connector 396

    9.4 处理HTTP请求 399

    9.4.1 Accept成功 399

    9.4.2 请求处理 401

    展开全文
  • Java高并发解决方案

    2021-04-09 16:26:07
    电商的秒杀和抢购,对我们来说,都不是一个陌生的东西。...在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个Web系统遇到了很多的问题和挑战。如果Web系统不做针对性的优化,会轻而...

    电商的秒杀和抢购,对我们来说,都不是一个陌生的东西。然而,从技术的角度来说,这对于Web系统是一个巨大的考验。当一个Web系统,在一秒钟内收到数以万计甚至更多请求时,系统的优化和稳定至关重要。这次我们会关注秒杀和抢购的技术实现和优化,同时,从技术层面揭开,为什么我们总是不容易抢到火车票的原因?

    一、大规模并发带来的挑战

    在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个Web系统遇到了很多的问题和挑战。如果Web系统不做针对性的优化,会轻而易举地陷入到异常状态。我们现在一起来讨论下,优化的思路和方法哈。

    1.请求接口的合理设计

    一个秒杀或者抢购页面,通常分为2个部分,一个是静态的HTML等内容,另一个就是参与秒杀的Web后台请求接口。

    通常静态HTML等内容,是通过CDN的部署,一般压力不大,核心瓶颈实际上在后台请求接口上。这个后端接口,必须能够支持高并发请求,同时,非常重要的一点,必须尽可能“快”,在最短的时间里返回用户的请求结果。为了实现尽可能快这一点,接口的后端存储使用内存级别的操作会更好一点。仍然直接面向MySQL之类的存储是不合适的,如果有这种复杂业务的需求,都建议采用异步写入。

    当然,也有一些秒杀和抢购采用“滞后反馈”,就是说秒杀当下不知道结果,一段时间后才可以从页面中看到用户是否秒杀成功。但是,这种属于“偷懒”行为,同时给用户的体验也不好,容易被用户认为是“暗箱操作”。

    2.高并发的挑战:一定要“快”

    我们通常衡量一个Web系统的吞吐率的指标是QPS(Query Per Second,每秒处理请求数),解决每秒数万次的高并发场景,这个指标非常关键。举个例子,我们假设处理一个业务请求平均响应时间为100ms,同时,系统内有20台Apache的Web服务器,配置MaxClients为500个(表示Apache的最大连接数目)。

    那么,我们的Web系统的理论峰值QPS为(理想化的计算方式):

    20*500/0.1 = 100000 (10万QPS)

    咦?我们的系统似乎很强大,1秒钟可以处理完10万的请求,5w/s的秒杀似乎是“纸老虎”哈。实际情况,当然没有这么理想。在高并发的实际场景下,机器都处于高负载的状态,在这个时候平均响应时间会被大大增加。

    就Web服务器而言,Apache打开了越多的连接进程,CPU需要处理的上下文切换也越多,额外增加了CPU的消耗,然后就直接导致平均响应时间增加。因此上述的MaxClient数目,要根据CPU、内存等硬件因素综合考虑,绝对不是越多越好。可以通过Apache自带的abench来测试一下,取一个合适的值。然后,我们选择内存操作级别的存储的Redis,在高并发的状态下,存储的响应时间至关重要。网络带宽虽然也是一个因素,不过,这种请求数据包一般比较小,一般很少成为请求的瓶颈。负载均衡成为系统瓶颈的情况比较少,在这里不做讨论哈。

    那么问题来了,假设我们的系统,在5w/s的高并发状态下,平均响应时间从100ms变为250ms(实际情况,甚至更多):

    20*500/0.25 = 40000 (4万QPS)

    于是,我们的系统剩下了4w的QPS,面对5w每秒的请求,中间相差了1w。

    然后,这才是真正的恶梦开始。举个例子,高速路口,1秒钟来5部车,每秒通过5部车,高速路口运作正常。突然,这个路口1秒钟只能通过4部车,车流量仍然依旧,结果必定出现大塞车。(5条车道忽然变成4条车道的感觉)

    同理,某一个秒内,20*500个可用连接进程都在满负荷工作中,却仍然有1万个新来请求,没有连接进程可用,系统陷入到异常状态也是预期之内。

    其实在正常的非高并发的业务场景中,也有类似的情况出现,某个业务请求接口出现问题,响应时间极慢,将整个Web请求响应时间拉得很长,逐渐将Web服务器的可用连接数占满,其他正常的业务请求,无连接进程可用。

    更可怕的问题是,是用户的行为特点,系统越是不可用,用户的点击越频繁,恶性循环最终导致“雪崩”(其中一台Web机器挂了,导致流量分散到其他正常工作的机器上,再导致正常的机器也挂,然后恶性循环),将整个Web系统拖垮。

    3.重启与过载保护

    如果系统发生“雪崩”,贸然重启服务,是无法解决问题的。最常见的现象是,启动起来后,立刻挂掉。这个时候,最好在入口层将流量拒绝,然后再将重启。如果是redis/memcache这种服务也挂了,重启的时候需要注意“预热”,并且很可能需要比较长的时间。

    秒杀和抢购的场景,流量往往是超乎我们系统的准备和想象的。这个时候,过载保护是必要的。如果检测到系统满负载状态,拒绝请求也是一种保护措施。在前端设置过滤是最简单的方式,但是,这种做法是被用户“千夫所指”的行为。更合适一点的是,将过载保护设置在CGI入口层,快速将客户的直接请求返回。

    二、作弊的手段:进攻与防守

    秒杀和抢购收到了“海量”的请求,实际上里面的水分是很大的。不少用户,为了“抢“到商品,会使用“刷票工具”等类型的辅助工具,帮助他们发送尽可能多的请求到服务器。还有一部分高级用户,制作强大的自动请求脚本。这种做法的理由也很简单,就是在参与秒杀和抢购的请求中,自己的请求数目占比越多,成功的概率越高。

    这些都是属于“作弊的手段”,不过,有“进攻”就有“防守”,这是一场没有硝烟的战斗哈。

    1.同一个账号,一次性发出多个请求

    部分用户通过浏览器的插件或者其他工具,在秒杀开始的时间里,以自己的账号,一次发送上百甚至更多的请求。实际上,这样的用户破坏了秒杀和抢购的公平性。

    这种请求在某些没有做数据安全处理的系统里,也可能造成另外一种破坏,导致某些判断条件被绕过。例如一个简单的领取逻辑,先判断用户是否有参与记录,如果没有则领取成功,最后写入到参与记录中。这是个非常简单的逻辑,但是,在高并发的场景下,存在深深的漏洞。多个并发请求通过负载均衡服务器,分配到内网的多台Web服务器,它们首先向存储发送查询请求,然后,在某个请求成功写入参与记录的时间差内,其他的请求获查询到的结果都是“没有参与记录”。这里,就存在逻辑判断被绕过的风险。

    应对方案:

    在程序入口处,一个账号只允许接受1个请求,其他请求过滤。不仅解决了同一个账号,发送N个请求的问题,还保证了后续的逻辑流程的安全。实现方案,可以通过Redis这种内存缓存服务,写入一个标志位(只允许1个请求写成功,结合watch的乐观锁的特性),成功写入的则可以继续参加。

    或者,自己实现一个服务,将同一个账号的请求放入一个队列中,处理完一个,再处理下一个。

    2.多个账号,一次性发送多个请求

    很多公司的账号注册功能,在发展早期几乎是没有限制的,很容易就可以注册很多个账号。因此,也导致了出现了一些特殊的工作室,通过编写自动注册脚本,积累了一大批“僵尸账号”,数量庞大,几万甚至几十万的账号不等,专门做各种刷的行为(这就是微博中的“僵尸粉“的来源)。举个例子,例如微博中有转发抽奖的活动,如果我们使用几万个“僵尸号”去混进去转发,这样就可以大大提升我们中奖的概率。

    这种账号,使用在秒杀和抢购里,也是同一个道理。例如,iPhone官网的抢购,火车票黄牛党。

    应对方案:

    这种场景,可以通过检测指定机器IP请求频率就可以解决,如果发现某个IP请求频率很高,可以给它弹出一个验证码或者直接禁止它的请求:

    弹出验证码,最核心的追求,就是分辨出真实用户。因此,大家可能经常发现,网站弹出的验证码,有些是“鬼神乱舞”的样子,有时让我们根本无法看清。他们这样做的原因,其实也是为了让验证码的图片不被轻易识别,因为强大的“自动脚本”可以通过图片识别里面的字符,然后让脚本自动填写验证码。实际上,有一些非常创新的验证码,效果会比较好,例如给你一个简单问题让你回答,或者让你完成某些简单操作(例如百度贴吧的验证码)。
    直接禁止IP,实际上是有些粗暴的,因为有些真实用户的网络场景恰好是同一出口IP的,可能会有“误伤“。但是这一个做法简单高效,根据实际场景使用可以获得很好的效果。

    3.多个账号,不同IP发送不同请求

    所谓道高一尺,魔高一丈。有进攻,就会有防守,永不休止。这些“工作室”,发现你对单机IP请求频率有控制之后,他们也针对这种场景,想出了他们的“新进攻方案”,就是不断改变IP。

    有同学会好奇,这些随机IP服务怎么来的。有一些是某些机构自己占据一批独立IP,然后做成一个随机代理IP的服务,有偿提供给这些“工作室”使用。还有一些更为黑暗一点的,就是通过木马黑掉普通用户的电脑,这个木马也不破坏用户电脑的正常运作,只做一件事情,就是转发IP包,普通用户的电脑被变成了IP代理出口。通过这种做法,黑客就拿到了大量的独立IP,然后搭建为随机IP服务,就是为了挣钱。

    应对方案:

    说实话,这种场景下的请求,和真实用户的行为,已经基本相同了,想做分辨很困难。再做进一步的限制很容易“误伤“真实用户,这个时候,通常只能通过设置业务门槛高来限制这种请求了,或者通过账号行为的”数据挖掘“来提前清理掉它们。

    僵尸账号也还是有一些共同特征的,例如账号很可能属于同一个号码段甚至是连号的,活跃度不高,等级低,资料不全等等。根据这些特点,适当设置参与门槛,例如限制参与秒杀的账号等级。通过这些业务手段,也是可以过滤掉一些僵尸号。

    4.火车票的抢购

    看到这里,同学们是否明白你为什么抢不到火车票?如果你只是老老实实地去抢票,真的很难。通过多账号的方式,火车票的黄牛将很多车票的名额占据,部分强大的黄牛,在处理验证码方面,更是“技高一筹“。

    高级的黄牛刷票时,在识别验证码的时候使用真实的人,中间搭建一个展示验证码图片的中转软件服务,真人浏览图片并填写下真实验证码,返回给中转软件。对于这种方式,验证码的保护限制作用被废除了,目前也没有很好的解决方案。

    因为火车票是根据身份证实名制的,这里还有一个火车票的转让操作方式。大致的操作方式,是先用买家的身份证开启一个抢票工具,持续发送请求,黄牛账号选择退票,然后黄牛买家成功通过自己的身份证购票成功。当一列车厢没有票了的时候,是没有很多人盯着看的,况且黄牛们的抢票工具也很强大,即使让我们看见有退票,我们也不一定能抢得过他们哈。

    最终,黄牛顺利将火车票转移到买家的身份证下。

    解决方案:

    并没有很好的解决方案,唯一可以动心思的也许是对账号数据进行“数据挖掘”,这些黄牛账号也是有一些共同特征的,例如经常抢票和退票,节假日异常活跃等等。将它们分析出来,再做进一步处理和甄别。

    三、高并发下的数据安全

    我们知道在多线程写入同一个文件的时候,会存现“线程安全”的问题(多个线程同时运行同一段代码,如果每次运行结果和单线程运行的结果是一样的,结果和预期相同,就是线程安全的)。如果是MySQL数据库,可以使用它自带的锁机制很好的解决问题,但是,在大规模并发的场景中,是不推荐使用MySQL的。秒杀和抢购的场景中,还有另外一个问题,就是“超发”,如果在这方面控制不慎,会产生发送过多的情况。我们也曾经听说过,某些电商搞抢购活动,买家成功拍下后,商家却不承认订单有效,拒绝发货。这里的问题,也许并不一定是商家奸诈,而是系统技术层面存在超发风险导致的。

    1.超发的原因

    假设某个抢购场景中,我们一共只有100个商品,在最后一刻,我们已经消耗了99个商品,仅剩最后一个。这个时候,系统发来多个并发请求,这批请求读取到的商品余量都是99个,然后都通过了这一个余量判断,最终导致超发。(同文章前面说的场景)

    在上面的这个图中,就导致了并发用户B也“抢购成功”,多让一个人获得了商品。这种场景,在高并发的情况下非常容易出现。

    2.悲观锁思路

    解决线程安全的思路很多,可以从“悲观锁”的方向开始讨论。

    悲观锁,也就是在修改数据的时候,采用锁定状态,排斥外部请求的修改。遇到加锁的状态,就必须等待。

    虽然上述的方案的确解决了线程安全的问题,但是,别忘记,我们的场景是“高并发”。也就是说,会很多这样的修改请求,每个请求都需要等待“锁”,某些线程可能永远都没有机会抢到这个“锁”,这种请求就会死在那里。同时,这种请求会很多,瞬间增大系统的平均响应时间,结果是可用连接数被耗尽,系统陷入异常。

    3.FIFO队列思路

    那好,那么我们稍微修改一下上面的场景,我们直接将请求放入队列中的,采用FIFO(First Input First Output,先进先出),这样的话,我们就不会导致某些请求永远获取不到锁。看到这里,是不是有点强行将多线程变成单线程的感觉哈。

    然后,我们现在解决了锁的问题,全部请求采用“先进先出”的队列方式来处理。那么新的问题来了,高并发的场景下,因为请求很多,很可能一瞬间将队列内存“撑爆”,然后系统又陷入到了异常状态。或者设计一个极大的内存队列,也是一种方案,但是,系统处理完一个队列内请求的速度根本无法和疯狂涌入队列中的数目相比。也就是说,队列内的请求会越积累越多,最终Web系统平均响应时候还是会大幅下降,系统还是陷入异常。

    4.乐观锁思路

    这个时候,我们就可以讨论一下“乐观锁”的思路了。乐观锁,是相对于“悲观锁”采用更为宽松的加锁机制,大都是采用带版本号(Version)更新。实现就是,这个数据所有请求都有资格去修改,但会获得一个该数据的版本号,只有版本号符合的才能更新成功,其他的返回抢购失败。这样的话,我们就不需要考虑队列的问题,不过,它会增大CPU的计算开销。但是,综合来说,这是一个比较好的解决方案。

    5.缓存服务器

    Redis分布式要保证数据都能能够平均的缓存到每一台机器,首先想到的做法是对数据进行分片,因为Redis是key-value存储的,首先想到的是Hash分片,可能的做法是对key进行哈希运算,得到一个long值对分布式的数量取模会得到一个一个对应数据库的一个映射,没有读取就可以定位到这台数据库

    有很多软件和服务都“乐观锁”功能的支持,例如Redis中的watch就是其中之一。通过这个实现,我们保证了数据的安全。

    四、小结

    互联网正在高速发展,使用互联网服务的用户越多,高并发的场景也变得越来越多。电商秒杀和抢购,是两个比较典型的互联网高并发场景。虽然我们解决问题的具体技术方案可能千差万别,但是遇到的挑战却是相似的,因此解决问题的思路也异曲同工。

    个人整理并发解决方案。

    a.应用层面:读写分离、缓存、队列、集群、令牌、系统拆分、隔离、系统升级(可水平扩容方向)。
    b.时间换空间:降低单次请求时间,这样在单位时间内系统并发就会提升。
    c.空间换时间:拉长整体处理业务时间,换取后台系统容量空间。

     

    展开全文
  • java高并发:并发:当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,...

    java高并发:

    并发:当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。.这种方式我们称之为并发(Concurrent)。

    对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了。而并发问题是绝大部分的程序员头疼的问题,

    、同步和异步的区别和联系

    所谓同步,可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是出于阻塞的,只有接收到

    返回的值或消息后才往下执行其它的命令。

    异步,执行完函数或方法后,不必阻塞性地等待返回值或消息,只需要向系统委托一个异步过程,那么当系统接收到返回

    值或消息时,系统会自动触发委托的异步过程,从而完成一个完整的流程。

    同步在一定程度上可以看做是单线程,这个线程请求一个方法后就待这个方法给他回复,否则他不往下执行(死心眼)。

    同步就是一件事,一件事情一件事的做。

    异步就是,做一件事情,不引响做其他事情。异步在一定程度上可以看做是多线程的(废话,一个线程怎么叫异步),请求一个方法后,就不管了,继续执行其他的方法。

    脏数据

    脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这

    个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是脏数据(Dirty Data),依据脏数据所做的操作可能是不正确的。

    不可重复读

    不可重复读是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读

    2、如何处理并发和同步

    今天讲的如何处理并发和同同步问题主要是通过锁机制。

    我们需要明白,锁机制有两个层面。

    一种是代码层次上的,如java中的同步锁,典型的就是同步关键字synchronized,这里我不在做过多的讲解,

    另外一种是数据库层次上的,比较典型的就是悲观锁和乐观锁。这里我们重点讲解的就是悲观锁(传统的物理锁)和乐观锁。

    悲观锁(Pessimistic Locking):

    悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自 外部系统的事务处理)修改持保守态度,因此,

    在整个数据处理过程中,将数据处于锁定状态。

    悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能 真正保证数据访问的排他性,否则,即使在本系统

    中实现了加锁机制,也无法保证外部系 统不会修改数据)。

    一个典型的倚赖数据库的悲观锁调用:

    select * from account where name=”Erica” for update

    这条 sql 语句锁定了 account 表中所有符合检索条件( name=”Erica” )的记录。

    本次事务提交之前(事务提交时会释放事务过程中的锁),外界无法修改这些记录。

    Hibernate 的悲观锁,也是基于数据库的锁机制实现。

    下面的代码实现了对查询记录的加锁:

    String hqlStr ="from TUser as user where user.name='Erica'";

    Query query = session.createQuery(hqlStr);

    query.setLockMode("user",LockMode.UPGRADE); // 加锁

    List userList = query.list();// 执行查询,获取数据

    query.setLockMode 对查询语句中,特定别名所对应的记录进行加锁(我们为 TUser 类指定了一个别名 “user” ),这里也就是对

    返回的所有 user 记录进行加锁。

    观察运行期 Hibernate 生成的 SQL 语句:

    select tuser0_.id as id, tuser0_.name as name, tuser0_.group_id

    as group_id, tuser0_.user_type as user_type, tuser0_.sex as sex

    from t_user tuser0_ where (tuser0_.name='Erica' ) for update

    这里 Hibernate 通过使用数据库的 for update 子句实现了悲观锁机制。

    Hibernate 的加锁模式有:

    Ø LockMode.NONE : 无锁机制。

    Ø LockMode.WRITE : Hibernate 在 Insert 和 Update 记录的时候会自动获取

    Ø LockMode.READ : Hibernate 在读取记录的时候会自动获取。

    以上这三种锁机制一般由 Hibernate 内部使用,如 Hibernate 为了保证 Update

    过程中对象不会被外界修改,会在 save 方法实现中自动为目标对象加上 WRITE 锁。

    Ø LockMode.UPGRADE :利用数据库的 for update 子句加锁。

    Ø LockMode. UPGRADE_NOWAIT : Oracle 的特定实现,利用 Oracle 的 for

    update nowait 子句实现加锁。

    上面这两种锁机制是我们在应用层较为常用的,加锁一般通过以下方法实现:

    Criteria.setLockMode

    Query.setLockMode

    Session.lock

    注意,只有在查询开始之前(也就是 Hiberate 生成 SQL 之前)设定加锁,才会

    真正通过数据库的锁机制进行加锁处理,否则,数据已经通过不包含 for update

    子句的 Select SQL 加载进来,所谓数据库加锁也就无从谈起。

    为了更好的理解select... for update的锁表的过程,本人将要以mysql为例,进行相应的讲解

    1、要测试锁定的状况,可以利用MySQL的Command Mode ,开二个视窗来做测试。

    需要注意的是for update要放到mysql的事务中,即begin和commit中,否者不起作用。

    乐观锁(Optimistic Locking):

    相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依 靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之

    而来的就是数据库 性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。 如一个金融系统,当某个操作员读取用户的数据,并在读出的用户数

    据的基础上进 行修改时(如更改用户帐户余额),如果采用悲观锁机制,也就意味着整个操作过 程中(从操作员读出数据、开始修改直至提交修改结果的全

    过程,甚至还包括操作 员中途去煮咖啡的时间),数据库记录始终处于加锁状态,可以想见,如果面对几 百上千个并发,这样的情况将导致怎样的后果。 乐

    观锁机制在一定程度上解决了这个问题。

    乐观锁,大多是基于数据版本   Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通

    过为数据库表增加一个 “version” 字段来 实现。 读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提 交数据的版本数据与数据

    库表对应记录的当前版本信息进行比对,如果提交的数据 版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。对于上面修改用户帐户信息

    的例子而言,假设数据库中帐户信息表中有一个 version 字段,当前值为 1 ;而当前帐户余额字段( balance )为 $100 。操作员 A 此时将其读出

    ( version=1 ),并从其帐户余额中扣除 $50( $100-$50 )。 2 在操作员 A 操作的过程中,操作员 B 也读入此用户信息( version=1 ),并 从其帐

    户余额中扣除 $20 ( $100-$20 )。 3 操作员 A 完成了修改工作,将数据版本号加一( version=2 ),连同帐户扣 除后余额( balance=$50 ),提交

    至数据库更新,此时由于提交数据版本大 于数据库记录当前版本,数据被更新,数据库记录 version 更新为 2 。 4 操作员 B 完成了操作,也将版本号加一

    ( version=2 )试图向数据库提交数 据( balance=$80 ),但此时比对数据库记录版本时发现,操作员 B 提交的 数据版本号为 2 ,数据库记录当前版

    本也为 2 ,不满足 “ 提交版本必须大于记 录当前版本才能执行更新 “ 的乐观锁策略,因此,操作员 B 的提交被驳回。 这样,就避免了操作员 B 用基于

    version=1 的旧数据修改的结果覆盖操作 员 A 的操作结果的可能。 从上面的例子可以看出,乐观锁机制避免了长事务中的数据库加锁开销(操作员 A

    和操作员 B 操作过程中,都没有对数据库数据加锁),大大提升了大并发量下的系 统整体性能表现。 需要注意的是,乐观锁机制往往基于系统中的数据存储

    逻辑,因此也具备一定的局 限性,如在上例中,由于乐观锁机制是在我们的系统中实现,来自外部系统的用户 余额更新操作不受我们系统的控制,因此可能

    会造成脏数据被更新到数据库中。在 系统设计阶段,我们应该充分考虑到这些情况出现的可能性,并进行相应调整(如 将乐观锁策略在数据库存储过程中实

    现,对外只开放基于此存储过程的数据更新途 径,而不是将数据库表直接对外公开)。 Hibernate 在其数据访问引擎中内置了乐观锁实现。如果不用考虑外

    部系统对数 据库的更新操作,利用 Hibernate 提供的透明化乐观锁实现,将大大提升我们的 生产力。

    一:高并发高负载类网站关注点之数据库

    没错,首先是数据库,这是大多数应用所面临的首个SPOF。尤其是Web2.0的应用,数据库的响应是首先要解决的。

    一般来说MySQL是最常用的,可能最初是一个mysql主机,当数据增加到100万以上,那么,MySQL的效能急剧下降。常用的优化措施是M-S(主-从)方式进行同步复制,将查询和操作和分别在不同的服务器上进行操作。我推荐的是M-M-Slaves方式,2个主Mysql,多个Slaves,需要注意的是,虽然有2个Master,但是同时只有1个是Active,我们可以在一定时候切换。之所以用2个M,是保证M不会又成为系统的SPOF。

    Slaves可以进一步负载均衡,可以结合LVS,从而将select操作适当的平衡到不同的slaves上。

    以上架构可以抗衡到一定量的负载,但是随着用户进一步增加,你的用户表数据超过1千万,这时那个M变成了SPOF。你不能任意扩充Slaves,否则复制同步的开销将直线上升,怎么办?我的方法是表分区,从业务层面上进行分区。最简单的,以用户数据为例。根据一定的切分方式,比如id,切分到不同的数据库集群去。

    全局数据库用于meta数据的查询。缺点是每次查询,会增加一次,比如你要查一个用户nightsailer,你首先要到全局数据库群找到nightsailer对应的cluster id,然后再到指定的cluster找到nightsailer的实际数据。

    每个cluster可以用m-m方式,或者m-m-slaves方式。这是一个可以扩展的结构,随着负载的增加,你可以简单的增加新的mysql cluster进去。

    二:高并发高负载网站的系统架构之HTML静态化

    三:高并发高负载类网站关注点之缓存、负载均衡、存储

    缓存是另一个大问题,我一般用memcached来做缓存集群,一般来说部署10台左右就差不多(10g内存池)。需要注意一点,千万不能用使用

    swap,最好关闭linux的swap。

    负载均衡/加速

    可能上面说缓存的时候,有人第一想的是页面静态化,所谓的静态html,我认为这是常识,不属于要点了。页面的静态化随之带来的是静态服务的

    负载均衡和加速。我认为Lighttped+Squid是最好的方式了。

    LVS lighttped====>squid(s) ====lighttpd

    上面是我经常用的。注意,我没有用apache,除非特定的需求,否则我不部署apache,因为我一般用php-fastcgi配合lighttpd,

    性能比apache+mod_php要强很多。

    squid的使用可以解决文件的同步等等问题,但是需要注意,你要很好的监控缓存的命中率,尽可能的提高的90%以上。

    存储

    存储也是一个大问题,一种是小文件的存储,比如图片这类。另一种是大文件的存储,比如搜索引擎的索引,一般单文件都超过2g以上。

    小文件的存储最简单的方法是结合lighttpd来进行分布。或者干脆使用Redhat的GFS,优点是应用透明,缺点是费用较高。我是指

    你购买盘阵的问题。我的项目中,存储量是2-10Tb,我采用了分布式存储。这里要解决文件的复制和冗余。

    这样每个文件有不同的冗余,这方面可以参考google的gfs的论文。

    大文件的存储,可以参考nutch的方案,现在已经独立为hadoop子项目。(你可以google it)

    四:高并发高负载网站的系统架构之图片服务器分离

    五:高并发高负载网站的系统架构之数据库集群和库表散列

    在数据库集群方面,很多数据库都有自己的解决方案,Oracle、Sybase等都有很好的方案,常用的MySQL提供的Master/Slave也是类似的方案,您使用了什么样的DB,就参考相应的解决方案来实施即可。

    上面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用DB类型的限制,于是我们需要从应用程序的角度来考虑改善系统架构,库表散列是常用并 且最有效的解决方案。我们在应用程序中安装业务和应用或者功能模块将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略对某个页面或者 功能进行更小的数据库散列,比如用户表,按照用户ID进行表散列,这样就能够低成本的提升系统的性能并且有很好的扩展性。sohu的论坛就是采用了这样的 架构,将论坛的用户、设置、帖子等信息进行数据库分离,然后对帖子、用户按照板块和ID进行散列数据库和表,最终可以在配置文件中进行简单的配置便能让系 统随时增加一台低成本的数据库进来补充系统性能。

    集群软件的分类:

    一般来讲,集群软件根据侧重的方向和试图解决的问题,分为三大类:高性能集群(High performance cluster,HPC)、负载均衡集群(Load balance cluster, LBC),高可用性集群(High availability cluster,HAC)。

    高性能集群(High performance cluster,HPC),它是利用一个集群中的多台机器共同完成同一件任务,使得完成任务的速度和可靠性都远远高于单机运行的效果。弥补了单机性能上的不足。该集群在天气预报、环境监控等数据量大,计算复杂的环境中应用比较多;

    负载均衡集群(Load balance cluster, LBC),它是利用一个集群中的多台单机,完成许多并行的小的工作。一般情况下,如果一个应用使用的人多了,那么用户请求的响应时间就会增大,机器的性能也会受到影响,如果使用负载均衡集群,那么集群中任意一台机器都能响应用户的请求,这样集群就会在用户发出服务请求之后,选择当时负载最小,能够提供最好的服务的这台机器来接受请求并相应,这样就可用用集群来增加系统的可用性和稳定性。这类集群在网站中使用较多;

    高可用性集群(High availability cluster,HAC),它是利用集群中系统 的冗余,当系统中某台机器发生损坏的时候,其他后备的机器可以迅速的接替它来启动服务,等待故障机的维修和返回。最大限度的保证集群中服务的可用性。这类系统一般在银行,电信服务这类对系统可靠性有高的要求的领域有着广泛的应用。

    六:高并发高负载网站的系统架构之缓存

    最基本的两种缓存。高级和分布式的缓存在后面讲述。

    架构方面的缓存,对Apache比较熟悉的人都能知道Apache提供了自己的缓存模块,也可以使用外加的Squid模块进行缓存,这两种方式均可以有效的提高Apache的访问响应能力。

    网站程序开发方面的缓存,Linux上提供的Memory Cache是常用的缓存接口,可以在web开发中使用,比如用Java开发的时候就可以调用MemoryCache对一些数据进行缓存和通讯共享,一些大 型社区使用了这样的架构。另外,在使用web语言开发的时候,各种语言基本都有自己的缓存模块和方法,PHP有Pear的Cache模块,Java就更多 了,.net不是很熟悉,相信也肯定有。

    Java开源缓存框架

    JBossCache/TreeCache JBossCache是一个复制的事务处理缓存,它允许你缓存企业级应用数据来更好的改善性能。缓存数据被自动复制,让你轻松进行Jboss服务器之间的集群工作。JBossCache能够通过Jboss应用服务或其他J2EE容器来运行一个Mbean服务,当然,它也能独立运行。 JBossCache包括两个模块:TreeCache和TreeCacheAOP。 TreeCache --是一个树形结构复制的事务处理缓存。 TreeCacheAOP --是一个“面向对象”缓存,它使用AOP来动态管理POJO

    OSCache OSCache标记库由OpenSymphony设计,它是一种开创性的JSP定制标记应用,提供了在现有JSP页面之内实现快速内存缓冲的功能。OSCache是个一个广泛采用的高性能的J2EE缓存框架,OSCache能用于任何Java应用程序的普通的缓存解决方案。OSCache有以下特点:缓存任何对象,你可以不受限制的缓存部分jsp页面或HTTP请求,任何java对象都可以缓存。 拥有全面的API--OSCache API给你全面的程序来控制所有的OSCache特性。 永久缓存--缓存能随意的写入硬盘,因此允许昂贵的创建(expensive-to-create)数据来保持缓存,甚至能让应用重启。 支持集群--集群缓存数据能被单个的进行参数配置,不需要修改代码。 缓存记录的过期--你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不需要时)。

    JCACHE JCACHE是一种即将公布的标准规范(JSR 107),说明了一种对Java对象临时在内存中进行缓存的方法,包括对象的创建、共享访问、假脱机(spooling)、失效、各JVM的一致性等。它可被用于缓存JSP内最经常读取的数据,如产品目录和价格列表。利用JCACHE,多数查询的反应时间会因为有缓存的数据而加快(内部测试表明反应时间大约快15倍)。

    Ehcache Ehcache出自Hibernate,在Hibernate中使用它作为数据缓存的解决方案。

    Java Caching System JCS是Jakarta的项目Turbine的子项目。它是一个复合式的缓冲工具。可以将对象缓冲到内存、硬盘。具有缓冲对象时间过期设定。还可以通过JCS构建具有缓冲的分布式构架,以实现高性能的应用。 对于一些需要频繁访问而每访问一次都非常消耗资源的对象,可以临时存放在缓冲区中,这样可以提高服务的性能。而JCS正是一个很好的缓冲工具。缓冲工具对于读操作远远多于写操作的应用性能提高非常显著。

    SwarmCache SwarmCache是一个简单而功能强大的分布式缓存机制。它使用IP组播来有效地在缓存的实例之间进行通信。它是快速提高集群式Web应用程序的性能的理想选择。

    ShiftOne ShiftOne Object Cache这个Java库提供了基本的对象缓存能力。实现的策略有先进先出(FIFO),最近使用(LRU),最不常使用(LFU)。所有的策略可以最大化元素的大小,最大化其生存时间。

    WhirlyCache Whirlycache是一个快速的、可配置的、存在于内存中的对象的缓存。它能够通过缓存对象来加快网站或应用程序的速度,否则就必须通过查询数据库或其他代价较高的处理程序来建立。

    Jofti Jofti可对在缓存层中(支持EHCache,JBossCache和OSCache)的对象或在支持Map接口的存储结构中的对象进行索引与搜索。这个框架还为对象在索引中的增删改提供透明的功能同样也为搜索提供易于使用的查询功能。

    cache4j cache4j是一个有简单API与实现快速的Java对象缓存。它的特性包括:在内存中进行缓存,设计用于多线程环境,两种实现:同步与阻塞,多种缓存清除策略:LFU, LRU, FIFO,可使用强引用(strong reference)与软引用(soft reference)存储对象。

    Open Terracotta 一个JVM级的开源群集框架,提供:HTTP Session复制,分布式缓存,POJO群集,跨越群集的JVM来实现分布式应用程序协调(采用代码注入的方式,所以你不需要修改任何)。

    sccache SHOP.COM使用的对象缓存系统。sccache是一个in-process cache和二级、共享缓存。它将缓存对象存储到磁盘上。支持关联Key,任意大小的Key和任意大小的数据。能够自动进行垃圾收集。

    Shoal Shoal是一个基于Java可扩展的动态集群框架,能够为构建容错、可靠和可用的Java应用程序提供了基础架构支持。这个框架还可以集成到不希望绑定到特定通信协议,但需要集群和分布式系统支持的任何Java产品中。Shoal是GlassFish和JonAS应用服务器的集群引擎。

    Simple-Spring-Memcached Simple-Spring-Memcached,它封装了对MemCached的调用,使MemCached的客户端开发变得超乎寻常的简单。

    展开全文
  • Java高并发秒杀项目

    2020-04-09 17:00:01
    Java高并发秒杀项目 项目代码见github,欢迎issue、fork、star。 项目实现 项目运行环境:Win10+Ubuntu18.04虚拟机,JDK1.8 项目中使用了关系型数据库MySQL(5.7.29)和非关系型数据库Redis(4.0.2),中间件...
  • 简单地说,启动多个线程调用同一实例的相同方法可以理解为高并发,如果需要,我可以给你一个简单的例子只通过java代码,有哪些方法可以保证并发超过100另一个响应是简单的建议,仅限于代码级和计算资源约束。java...
  • 如何设置高并发接口一、并发队列的选择二、请求接口的合理设计三、高并发下的数据安全3.1 超发的原因3.2 悲观锁思路3.3 FIFO队列思路3.4 乐观锁思路一、并发队列的选择Java的并发包提供了三个常用的并发队列实现,...
  • 一、 Apache JMeter工具1)简介JMeter——一个100%的纯java桌面应用,它是 Apache组织的开放源代码项目,它是功能和性能测试的工具。JMeter可以用于测试静态或者动态资源的性能(文件、Servlets、Perl脚本、java对象...
  • Java实现高并发的处理的方式

    千次阅读 2017-08-11 23:38:46
    高并发处理的方式
  • Java 高并发解决方案(电商的秒杀和抢购)

    万次阅读 多人点赞 2018-07-25 14:08:08
    电商的秒杀和抢购,对我们来说,都不是一个陌生的东西。然而,从技术的角度来说,这对于Web系统是一个巨大的考验。当一个Web系统,在...在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整...
  • Java高并发、秒杀电商项目--实战

    千次阅读 多人点赞 2020-04-22 17:39:28
    这个项目是根据我在慕课网上面学习的《Java秒杀系统方案优化 高性能高并发实战》这门课程后,又加了个支付宝支付的整合的一个项目。 这是一个基于java技术的手机秒杀网站主要是学习秒杀、多并发、性能提升方面的知识...
  • Java开发中多线程与高并发需要注意的 15 个细节

    千次阅读 多人点赞 2022-03-29 10:22:44
    (由于java jvm没有规定synchronized如何实现,所以理论上调整jvm也是可以降级锁的),争用大部分是自旋锁,占CPU但是不访问操作系统,所以是用户态,不是内核态,加锁解锁比经过内核态效率要。 执行时间长或线程...
  • BATJ最全架构技术合集:高并发+微服务+数据结构+SpringBoot 关于一线互联网大厂网站的一些特点:用户多,分布广泛、大流量,高并发、海量数据,服务高可用、安全环境恶劣,易受网络攻击、功能多,变更快,频繁发布...
  • 背景Disruptor是LMAX开发的一个性能队列,研发的初衷是解决内存队列的延迟问题(在性能测试中发现竟然与I/O操作处于同样的数量级)。基于Disruptor开发的系统单线程能支撑每秒600万订单,2010年在QCon演讲后,获得了...
  • JMeter主要用在对Java项目的压力测试,是高并发测试常用的工具之一,接下来楼主将用图形结合的方式带你快速入门JMeter的下载: 1.从官网下载JMeter压缩包:(输入网址http://jmeter.apache.org/) ...
  • java 高并发解决方案

    2020-02-08 13:58:40
    高并发由于分布式系统的问世,高并发(High Concurrency)通常是指通过设计保证系统能够同时并行处理很多请求。通俗来讲,高并发是指在同一个时间点,有很多用户同时的访问同...
  • Java处理高并发量访问的处理总结

    万次阅读 2017-08-29 23:49:11
    结合之前做的一个网站,项目中分了几个子项目,主要用到Redis,service(server)层和control层分离,有做了缓存,页面也是进行静态化(htm和freemarker),仔细想想,整个项目基本吻合高并发,负载均衡的处理。...
  • 一个小型的网站,比如个人网站,可以...已经细分到很细的方方面面,尤其对于大型网站来说,所采用的技术更是涉及面非常广,从硬件到软件、编程语言、数据库、WebServer、防火墙等各个领域都有了很的要求,已经不是
  • java高级软件架构师实战,高并发,分布式,集群,电商实战
  • 解决java中的高并发问题可以从硬件软件等方面入手,硬件如:服务器;软件如:系统缓存、页面静态化等。这里我写的是页面静态化的简单小例子。之所以将这个小例子记录下来是因为之前对页面静态化有误解,原以为静态化...
  • Jmeter----- java并发测试工具

    千次阅读 2019-11-05 20:15:36
    所以打算用定时失效的map去处理,但是由于是多线程,再失效的时候的这个map就需要用单例的双重锁去解决并发put会造成数据错乱等问题。在编写好代码后。需要有一款不同于postman的长时间压力测试测试工具来帮助测试...
  • 文章目录深入理解Java高并发一、并发的设计原则1、基础的并发概念1)基础概念2)同步的方法3)线程安全2、在并发应用中可能发生的问题1)资源竞争2)死锁3)资源饥饿4)优先级抢占3、并发算法的设计起始:串行算法1...
  • java高并发和负载均衡

    万次阅读 2018-01-02 11:07:10
    一个小型的网站,比如个人网站,可以...已经细分到很细的方方面面,尤其对于大型网站来说,所采用的技术更是涉及面非常广,从硬件到软件、编程语言、数据库、WebServer、防火墙等各个领域都有了很的要求,已经不是
  • JavaWeb 并发编程 与 高并发解决方案

    万次阅读 多人点赞 2018-09-12 03:41:00
    在这里写写我学习到和自己所理解的 Java高并发编程和高并发解决方案。现在在各大互联网公司中,随着日益增长的互联网服务需求,高并发处理已经是一个非常常见的问题,在这篇文章里面我们重点讨论两个方面的问题,一...
  • 公共阶级{并发测试与压力测试。私有静态int thread_num=200;私有静态int client_num=460;视酷eter压力测试并发数。私有静态地图关键字地图=新的哈希地图();并发压力测试。静态{python高并发压力测试。尝试{ISR=新...
  • java高并发解决方案

    万次阅读 2016-07-20 17:53:31
    高并发的时候是有很多用户在访问,导致出现系统数据不正确、丢失数据现象,所以想到 的是用队列解决,其实队列解决的方式也可以处理,比如我们在竞拍商品、转发评论微博或者是秒杀商品等,同一时间访问量特别大,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 87,120
精华内容 34,848
关键字:

java 高并发测试软件

java 订阅