jedis解决高并发的一些学习

1、高并发带来的问题就是  {公共资源 } 的读写不准确

2、解决高并发的几种场景:

  场景一)  同一个JVM进程(jee中就是同一个tomcat)中,公共资源在同一块内存中,使用synchronized关键字给代码块或是方法加锁,使得同一个代码块不会被同时调用;成员变量的数据类型尽量使用JUC中的atomic*等原子类,其中的方法都是原子操作,但是性能会有所降低;对于非原子类成员变量修饰符可以使用volatile(强制使用主存变量)。

    说明:JUC在此场景中的使用非常广泛,主要是CAS操作,而且多线程的公共资源都是在主存中进行读取,不会在寄存器中做修改;但是,会有一个ABA问题(比如说一个线程one从内存位置V中取出A,这时候另一个线程two也从内存中取出A,并且two进行了一些操作变成了B,然         后two又将V位置的数据变成A,这时候线程one进行CAS操作发现内存中仍然是A,然后one操作成功)

  场景二)  非同一个JVM进程(集群或分布式),公共资源在第三方缓存中(如redis),JUC的CAS操作会失效,这个时候想实现公共资源的正确调用只能依赖第三方的同步锁机制(如redis的WATCH监控和事务MULTI-EXEC的配合使用)

3、实际应用:jedis解决抢购的问题:

package com.thinkgem.jeesite;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Transaction;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by Administrator on 2017/9/29.
 */
public class JedisMainTest {
    static final JedisPool pool = new JedisPool(new JedisPoolConfig() {{
        setMaxIdle(1000);
        setMaxTotal(1000);
        setTestOnBorrow(true);
    }}, "127.0.0.1", 6379);

    static final  String watchkeys = "watchKeys";// 监视keys
    static final String goodsStore = "goodsStore";//库存的key
    static final int stores = 10;//库存量

    public static void main(String[] args) throws InterruptedException {

        ExecutorService executor = Executors.newFixedThreadPool(1000);
        ExecutorService executor1 = Executors.newFixedThreadPool(1000);
        Jedis jedis = pool.getResource();
        jedis.set(watchkeys, "0");// 重置watchkeys为0
        jedis.set(goodsStore,""+stores);
        jedis.del("setsucc", "setfail");// 清空抢成功的,与没有成功的
        jedis.close();

        for (int i = 0; i < 10000; i++) {// 测试一万人同时访问
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    for (int c = 0; c < 10; c++) {

                        executor1.execute(new MyRunnable());
                    }
                }
            });
//            Thread.sleep(50);
        }
        executor.shutdown();
    }

    static class MyRunnable implements Runnable {
/*TODO:未解决问题,一开始有两个以上的线程同时执行,会出现库存有剩余,但是同时执行的程序抢不到库存*/
        Jedis jedis = pool.getResource();

        public MyRunnable() {
        }

        @Override
        public void run() {
            try {

                jedis.watch(watchkeys);// 开始监视锁

                String val = jedis.get(goodsStore);
                int valint = Integer.valueOf(val);
                String userifo = UUID.randomUUID().toString();
                if (valint >0) {
                    Transaction tx = jedis.multi();// 开启事务

                    tx.decr(goodsStore);//库存量 -1
                    tx.incr(watchkeys);//修改监控变量

                    List<Object> list = tx.exec();// 提交事务,如果此时watchkeys被改动了,则返回null

                    //说明通过验证了,即库存还有剩余
                    if (list != null) {
                        System.out.println("用户:" + userifo + "抢购成功,当前抢购成功人数:"
                                + (stores-valint+1));
                    /* 抢购成功业务逻辑 */
                        jedis.sadd("setsucc", userifo);
                        Thread.sleep(900);//模拟业务执行时间
                    } else {
                        System.out.println("用户:" + userifo + "抢购失败,其他线程干扰");
                    /* 抢购失败业务逻辑 */
                        jedis.sadd("setfail", userifo);
                        Thread.sleep(400);//模拟业务执行时间
                    }

                } else {
                    System.out.println("用户:" + userifo + "抢购失败,库存以空");
                    jedis.sadd("setfail", userifo);
                    Thread.sleep(400);//模拟业务执行时间
                    // Thread.sleep(500);
                    return;
                }

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                jedis.close();
            }

        }

    }
}
时间: 2024-10-19 15:38:04

jedis解决高并发的一些学习的相关文章

每一个程序员都应该知道的高并发处理技巧、创业公司如何解决高并发问题、互联网高并发问题解决思路、caoz大神多年经验总结分享

本文来源于caoz梦呓公众号高并发专辑,以图形化.松耦合的方式,对互联网高并发问题做了详细解读与分析,"技术在短期内被高估,而在长期中又被低估",而不同的场景和人员成本又导致了巨头的方案可能并不适合创业公司,那么如何保证高并发问题不成为创业路上的拦路虎,是每一个全栈工程师.资深系统工程师.有理想的程序员必备的技能,希望本文助您寻找属于自己的"成金之路",发亮发光. 目录: 场景及解决方法解读 认识负载 数据跟踪 脑图.caoz大神公众号分享 参考资料 秉承知其然及其

Nginx和Tengine解决高并发和高可用,而非推荐Apache

什么是Nginx  什么是Tengine 看看国内大公司在用Nginx和Tengine吗? 步骤一:进入 https://www.taobao.com/,按F12.可看到 有很多APP对淘宝进行请求.随便点击一个, 步骤二:当然,可以看到,并不都在nginx里.比如还有Tengine...等其他.这个自行去看吧! 所以,学会一个知识,淘宝网站里,用到了很多,并非nginx一家.  Nginx和Apache的优缺点  进入Tengine官网 自行去看吧! 什么是高并发和负载均衡 如何解决高并发和负

《JAVA——帮你解决高并发秒杀》

[准备] 首先我们要考虑的是为什么要解决高并发,高并发瓶颈出现在哪里,有了解过的朋友肯定知道是在数据库,因为在大量请求去操作数据库时会出现数据的错乱,超卖,系统崩溃,mysql死锁等现象. [思路] (一). 页面静态化:就是将整个页面存储到redis中,下次访问时去读取redis中的页面值 (二).主要对整个网站的静态资源文件进行加速,如图片,css,js等 (三).数学验证码:用户在计算验证码结果时可以减少大量请求同时进入,减少redis, mysql,服务器的压力. (四).库存标识:这是

Java解决高并发秒杀

一:问题 首先我们要考虑的是为什么要解决高并发,高并发瓶颈出现在哪里,有了解过的朋友肯定知道是在数据库,因为在大量请求去操作数据库时会出现数据的错乱,超卖,系统崩溃,mysql死锁等现象. 二:思路 1. 页面静态化:就是将整个页面存储到redis中,下次访问时去读取redis中的页面值 2. cdn:主要对整个网站的静态资源文件进行加速,如图片,css,js等(去阿里看教程) 3.数学验证码:用户在计算验证码结果时可以减少大量请求同时进入,减少redis, mysql,服务器的压力. 4:库存

node第三课(node解决高并发的原理)

接着上一课继续学习. node结局高并发的原理 我们把node放在了中间,java只是往外传数据,node分发 http处理数据,node并发抗压比传统的平台要高,天猫就是先用的node服务器,就是说node现在有两个角色,一个处理所有的来自客户端的https请求,另一个就是为传统的服务器分发http请求,这样就解决的高并发的问题,第一种角色是全包了,第二种角色是分配 原文地址:https://www.cnblogs.com/JavascriptAndHtml5/p/9460263.html

面对峰值响应冲击,解决高并发的三大策略

当前在互联网+的大潮下,众所周知淘宝.京东这些交易系统每天产生的数据量都是海量的,每天的交易并发也是惊人的,尤其是"双11"."6.18"这些活动,对系统的峰值响应提出了非常高的要求,所以对系统架构也就有了很要的要求. 在写这篇博客的前2天,听说某系统在25人的用户量下就宕机了,实在让人震惊,所以捋了下互联网交易系统我们可以采取哪些技术来解决互联网平台下大数据量高并发的问题. 首先根据架构分层把不同技术进行了一些分类,如下图: 互联网技术架构分层策略图 接下来我会逐

今天被问到怎么解决高并发问题。

一个小型的网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统架构.性能的要求都很简单.随着互联网业务的不断丰富,网站相关的技术经过这些年的发展,已经细分到很细的方方面面,尤其对于大型网站来说,所采用的技术更是涉及面非常广,从硬件到软件.编程语言.数据库.WebServer.防火墙等各个领域都有了很高的要求,已经不是原来简单的html静态网站所能比拟的. 大型网站,比如门户网站,在面对大量用户访问.高并发请求方面,基本的解决方案

asp.net解决高并发的方案.[转]

最近几天一直在读代震军的博客,他是Discuz!NT的设计者,读了他的一系列关于Discuz!NT的架构设计文章,大呼过瘾,特别是Discuz!NT在解决高访问高并发时所设计的一系列方案,本人尤其感兴趣.写这篇文章的目的,算是对初次阅读之后的总结备忘吧,以便以后有时间亲自测试,如果能在生产环境中得到应用,那就更有参考价值了. 测试方法:本地模拟测试网站高访问高并发采用的测试工具是大名鼎鼎的Loadrunner,这个工具做测试的一般都知道.在代震军的博客中,有以下几篇介绍了通过Loadrunner

解决高并发

java处理高并发高负载类网站中数据库的设计方法(java教程,java处理大量数据,java高负载数据) 一:高并发高负载类网站关注点之数据库 没错,首先是数据库,这是大多数应用所面临的首个SPOF.尤其是Web2.0的应用,数据库的响应是首先要解决的. 一般来说MySQL是最常用的,可能最初是一个mysql主机,当数据增加到100万以上,那么,MySQL的效能急剧下降.常用的优化措施是M-S(主-从)方式进行同步复制,将查询和操作和分别在不同的服务器上进行操作.我推荐的是M-M-Slaves