对于一个互联网平台来说,高并发是经常会遇到的场景。最有代表性的比如秒杀和抢购。高并发会出现三个特点:

  1、高并发读取

  2、高并发写入(一致性)

  3、出现超卖问题

前端如何应对?

1、缓存静态数据,例如图片,html页面,js等

2、搭建负载均衡集群,目前采用较多的为nginx

3、进行ip限制,限制同一个ip单位时间内发起的请求数量。或者建立ip黑名单,避免恶意攻击

4、考虑系统降级。比如当达到系统负载的时候返回一个静态处理页面

后端如何应对?

1、采用mysql读写分离,但是当高并发的时候mysql性能会降低。 一般来说,MySQL的处理性能会随着并发thread上升而上升,但是到了一定的并发度之后会出现明显的拐点,之后一路下降,最终甚至会比单thread的性能还要差。比如加减库存的操作,通常并发量不高的做法为:update xxx set count=count-xx where curcount>xx;这样可以充分利用mysql的事务锁来避免出现超卖的情况。但是并发量上了后,会因为排他锁等待而大大降低性能。

2、采用redis数据库,前置到mysql。思路如下:

2.1系统启动后,初始化sku信息到redis数据库,记录其可用量和锁定量

2.2使用乐观锁,采用redis的watch机制。逻辑为:

1.定义门票号变量,设置初始值为0。watchkey

2.watch该变量,watch(watchkey);

3.使用redis事务加减库存。首先获取可用量和抢购量比较,如果curcount>buycount,那么正常执行减库存和加锁定量操作:

Redis用法详细说明

1、Pipeline

利用pipeline的方式从client打包多条命令一起发出,不需要等待单条命令的响应返回,而Redis服务端会处理完多条命令后会将多条命令的处理结果打包到一起返回给客户端。所以pipeline适合批处理作业可以提升效率如:

  1. public static void testMget() {
  2. Jedis jedis = RedisCacheClient.getInstrance().getClient();
  3. Set<String> keys = jedis.keys("cvfeedBackHandl_*");
  4. List<String> result = Lists.newArrayList();
  5. long t1 = System.currentTimeMillis();
  6. for (String key : keys) {
  7. result.add(jedis.get(key));
  8. }
  9. for (String src : result) {
  10. System.out.println(src);
  11. }
  12. System.out.println(System.currentTimeMillis() - t1);
  13. }
  14. public static void testPipline() {
  15. Jedis jedis = RedisCacheClient.getInstrance().getClient();
  16. Set<String> keys = jedis.keys("cvfeedBackHandl_*");
  17. List<Object> result = Lists.newArrayList();
  18. Pipeline pipelined = jedis.pipelined();
  19. long t1 = System.currentTimeMillis();
  20. for (String key : keys) {
  21. pipelined.<span style="font-family: Arial;">get</span>("testabcd");
  22. }
  23. result = pipelined.syncAndReturnAll();
  24. for (Object src : result) {
  25. System.out.println(src);
  26. }
  27. System.out.println(System.currentTimeMillis() - t1);
  28. }

如第一个方法执行的时间是82ms

第二个方法执行的时间是9ms

注意:pipeline和事务都是异步调用返回结果的,即并不是等待每条命令执行完立马返回结果而是等待所有命令执行完之后再返回结果。pipelined.syncAndReturnAll()返回的是参与打包执行的每条命令的结果。如果上面改成:

  1. for (String key : keys) {//keys长度为5
  2. pipelined.get(key);
  3. pipelined.del("testabcd");
  4. }

返回结果将是

  1. "test1"
  2. 1
  3. "test2"
  4. 0
  5. "test2"
  6. 0
  7. "test4"
  8. 0
  9. "test5"
  10. 0

2、事务

事务是保证事务内的所有命令是原子操作,一般配合watch使用,事务的执行结果和pipeline一样都是采用异步的方式获取结果,multi.exec()提交事务,如果执行成功,其返回的结果和pipeline一样是所有命令的返回值,如果事务里面有两个命令那么事务的exec返回值会把两个命令的返回值组合在一起返回。如果事务被取消返回null。

3、watch

一般是和事务一起使用,当对某个key进行watch后如果其他的客户端对这个key进行了更改,那么本次事务会被取消,事务的exec会返回null。jedis.watch(key)都会返回OK
eg:

  1. public static void testWach(){
  2. Jedis jedis = RedisCacheClient.getInstrance().getClient();
  3. String watch = jedis.watch("testabcd");
  4. System.out.println(Thread.currentThread().getName()+"--"+watch);
  5. Transaction multi = jedis.multi();
  6. multi.set("testabcd", "23432");
  7. try {
  8. Thread.sleep(3000);
  9. } catch (InterruptedException e) {
  10. e.printStackTrace();
  11. }
  12. List<Object> exec = multi.exec();
  13. System.out.println("---"+exec);
  14. jedis.unwatch();
  15. }
  16. public static void testWatch2(){
  17. Jedis jedis = RedisCacheClient.getInstrance().getClient();
  18. String watch = jedis.watch("testabcd2");
  19. System.out.println(Thread.currentThread().getName()+"--"+watch);
  20. Transaction multi = jedis.multi();
  21. multi.set("testabcd", "125");
  22. List<Object> exec = multi.exec();
  23. System.out.println("--->>"+exec);
  24. }

Thread-2--OK
Thread-0--OK
--->>[OK]

---null//事务取消

4、事务与管道

当对某个key进行watch时,如果其他的客户端对key进行了更改事务可以做到取消事务操作但是管道不可以

【Redis】1、Jedis对管道、事务以及Watch的操作来应对高并发的更多相关文章

  1. EasyCMS在幼儿园视频直播项目实战中以redis操作池的方式应对高并发的redis操作问题

    在之前的博客< EasyDarwin幼教云视频平台在幼教平台领域大放异彩!>中我们也介绍到,EasyCMS+EasyDarwin+redis形成的EasyDarwin云平台方案,在幼教平台 ...

  2. 应对高并发场景的redis加锁技巧

    // 获取锁getLock() {    // 是否有正在执行的线程    boolean hasLock = false;    try {        hasLock = redisClient ...

  3. 使用Redis中间件解决商品秒杀活动中出现的超卖问题(使用Java多线程模拟高并发环境)

    一.引入Jedis依赖 可以新建Spring或Maven工程,在pom文件中引入Jedis依赖: <dependency> <groupId>redis.clients< ...

  4. redis高可用,保证高并发

    目录 redis如何通过读写分离来承载读请求QPS超过10万+ redis replication以及master持久化对主从架构的安全意义 redis主从复制原理.断点续传.无磁盘化复制.过期key ...

  5. Redis的高并发、持久化、高可用架构设计

    就是如果你用redis缓存技术的话,肯定要考虑如何用redis来加多台机器,保证redis是高并发的,还有就是如何让Redis保证自己不是挂掉以后就直接死掉了,redis高可用 我这里会选用我之前讲解 ...

  6. 2020重新出发,NOSQL,redis高并发系统的分析和设计

    高并发系统的分析和设计 任何系统都不是独立于业务进行开发的,真正的系统是为了实现业务而开发的,所以开发高并发网站抢购时,都应该先分析业务需求和实际的场景,在完善这些需求之后才能进入系统开发阶段. 没有 ...

  7. redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: 断开的管道 (Write failed)

    昨晚,包发到测试环境中,出现redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: 断开的 ...

  8. jedis使用管道(pipeline)对redis进行读写(使用hmset、hgetall测试)

    一般情况下,Redis Client端发出一个请求后,通常会阻塞并等待Redis服务端处理,Redis服务端处理完后请求命令后会将结果通过响应报文返回给Client.这有点类似于HBase的Scan, ...

  9. redis客户端--jedis

    一.jedis jedis 是 redis推荐的java客户端.通过Jedis我们可以很方便地使用java代码的方式,对redis进行操作.jedis使用起来比较简单,它的操作方法与redis命令相类 ...

随机推荐

  1. WebAPI中发送字节数组

    今天工作中遇到了一个情景: 前端向后台发送一个请求,希望后台返回一组数据,由于后台返回的数据量很大,希望尽可能压缩响应的大小 我的想法:后台将数据(Short的数组)直接转换成Byte[]  然后将b ...

  2. C# 动态创建SQL数据库(二)

    使用Entity Framework  创建数据库与表 前面文章有说到使用SQL语句动态创建数据库与数据表,这次直接使用Entriy Framwork 的ORM对象关系映射来创建数据库与表 一 新建项 ...

  3. JQuery 知识

    1.修改标签内容: *html( )  相当于innerHTML * text(  )  相当于innerText 2.属性操作: *attr(  )  读/写/添加/设置属性 *removeAttr ...

  4. [学习笔记]状压dp

    状压 \(dp\) 1.[SDOI2009]Bill的挑战 \(f[i][j]\) 表示匹配到字符串的第 \(i\) 位状态为 \(j\) 的方案数 那么方程就很明显了,每次枚举第 \(i\) 位的字 ...

  5. java的基本数据类型--四类八种

    java的数据类型 1.分为基本数据类型和引用数据类型 基本数据类型的分类:整数型: byte  占用一个字节 范围-128-127 short 占用两个字节  -2^15~2^15-1 int    ...

  6. Oracle死锁查询及批量处理

    一.数据库死锁的现象程序在执行的过程中,点击确定或保存按钮,程序没有响应,也没有出现报错. 二.死锁的原理当对于数据库某个表的某一列做更新或删除等操作,执行完毕后该条语句不提交,另一条对于这一列数据做 ...

  7. flume常用组件

    Flume组件 1.   Source NetCat Source:绑定的端口(tcp.udp),将流经端口的每一个文本行数据作为Event输入: type:source的类型,必须是netcat. ...

  8. 一、Linq简介

    语言集成查询Language Integrated Query(LINQ)是一系列将查询功能集成到C#语言的技术统称. 传统数据查询的缺点: 简单的字符串查询,没有编译时类型检查或Intellisen ...

  9. 全网最详细的Hadoop HA集群启动后,两个namenode都是standby的解决办法(图文详解)

    不多说,直接上干货! 解决办法 因为,如下,我的Hadoop HA集群. 1.首先在hdfs-site.xml中添加下面的参数,该参数的值默认为false: <property> < ...

  10. Java 9 中,我们可以在匿名类中使用 <> 操作符

    不说了,直接上代码: public class NewTest { public static void main(String[] args) { N<Integer> n1 = new ...