设为首页 收藏本站
查看: 943|回复: 0

[经验分享] 【Redis】1、Jedis对管道、事务以及Watch的操作来应对高并发

[复制链接]

尚未签到

发表于 2017-12-21 17:51:49 | 显示全部楼层 |阅读模式
  对于一个互联网平台来说,高并发是经常会遇到的场景。最有代表性的比如秒杀和抢购。高并发会出现三个特点:
  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适合批处理作业可以提升效率如:
[java] view plain copy  print?

  • public static void testMget() {
  •         Jedis jedis = RedisCacheClient.getInstrance().getClient();
  •         Set<String> keys = jedis.keys("cvfeedBackHandl_*");
  •         List<String> result = Lists.newArrayList();
  •         long t1 = System.currentTimeMillis();
  •         for (String key : keys) {
  •             result.add(jedis.get(key));
  •         }
  •         for (String src : result) {
  •             System.out.println(src);
  •         }
  •         System.out.println(System.currentTimeMillis() - t1);
  •     }

  •     public static void testPipline() {
  •         Jedis jedis = RedisCacheClient.getInstrance().getClient();
  •         Set<String> keys = jedis.keys("cvfeedBackHandl_*");
  •         List<Object> result = Lists.newArrayList();
  •         Pipeline pipelined = jedis.pipelined();
  •         long t1 = System.currentTimeMillis();
  •         for (String key : keys) {
  •             pipelined.<span style="font-family: Arial;">get</span>("testabcd");
  •         }
  •         result = pipelined.syncAndReturnAll();
  •         for (Object src : result) {
  •             System.out.println(src);
  •         }
  •         System.out.println(System.currentTimeMillis() - t1);
  •     }
  如第一个方法执行的时间是82ms
  第二个方法执行的时间是9ms
  注意:pipeline和事务都是异步调用返回结果的,即并不是等待每条命令执行完立马返回结果而是等待所有命令执行完之后再返回结果。pipelined.syncAndReturnAll()返回的是参与打包执行的每条命令的结果。如果上面改成:
[java] view plain copy  print?

  • for (String key : keys) {//keys长度为5
  •             pipelined.get(key);
  •             pipelined.del("testabcd");
  • }
  返回结果将是
[java] view plain copy  print?

  • "test1"
  • 1
  • "test2"
  • 0
  • "test2"
  • 0
  • "test4"
  • 0
  • "test5"
  • 0
  2、事务
  事务是保证事务内的所有命令是原子操作,一般配合watch使用,事务的执行结果和pipeline一样都是采用异步的方式获取结果,multi.exec()提交事务,如果执行成功,其返回的结果和pipeline一样是所有命令的返回值,如果事务里面有两个命令那么事务的exec返回值会把两个命令的返回值组合在一起返回。如果事务被取消返回null。
  3、watch
  一般是和事务一起使用,当对某个key进行watch后如果其他的客户端对这个key进行了更改,那么本次事务会被取消,事务的exec会返回null。jedis.watch(key)都会返回OK
  eg:
[java] view plain copy  print?

  • public static void testWach(){
  •        Jedis jedis = RedisCacheClient.getInstrance().getClient();
  •        String watch = jedis.watch("testabcd");
  •        System.out.println(Thread.currentThread().getName()+"--"+watch);
  •        Transaction multi = jedis.multi();
  •        multi.set("testabcd", "23432");
  •        try {
  •            Thread.sleep(3000);
  •        } catch (InterruptedException e) {
  •            e.printStackTrace();
  •        }
  •        List<Object> exec = multi.exec();
  •        System.out.println("---"+exec);
  •        jedis.unwatch();
  •    }
  •    public static void testWatch2(){
  •        Jedis jedis = RedisCacheClient.getInstrance().getClient();
  •        String watch = jedis.watch("testabcd2");
  •        System.out.println(Thread.currentThread().getName()+"--"+watch);
  •        Transaction multi = jedis.multi();
  •        multi.set("testabcd", "125");
  •        List<Object> exec = multi.exec();
  •        System.out.println("--->>"+exec);
  •    }
  Thread-2--OK
  Thread-0--OK
  --->>[OK]
  ---null//事务取消
  4、事务与管道
  当对某个key进行watch时,如果其他的客户端对key进行了更改事务可以做到取消事务操作但是管道不可以

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-426569-1-1.html 上篇帖子: Redis【第二篇】集群搭建 下篇帖子: PHP 使用redis实现秒杀
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表