【Redis】1、Jedis对管道、事务以及Watch的操作来应对高并发
对于一个互联网平台来说,高并发是经常会遇到的场景。最有代表性的比如秒杀和抢购。高并发会出现三个特点:
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适合批处理作业可以提升效率如:
- 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()返回的是参与打包执行的每条命令的结果。如果上面改成:
- for (String key : keys) {//keys长度为5
- pipelined.get(key);
- pipelined.del("testabcd");
- }
返回结果将是
- "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:
- 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进行了更改事务可以做到取消事务操作但是管道不可以
【Redis】1、Jedis对管道、事务以及Watch的操作来应对高并发的更多相关文章
- EasyCMS在幼儿园视频直播项目实战中以redis操作池的方式应对高并发的redis操作问题
在之前的博客< EasyDarwin幼教云视频平台在幼教平台领域大放异彩!>中我们也介绍到,EasyCMS+EasyDarwin+redis形成的EasyDarwin云平台方案,在幼教平台 ...
- 应对高并发场景的redis加锁技巧
// 获取锁getLock() { // 是否有正在执行的线程 boolean hasLock = false; try { hasLock = redisClient ...
- 使用Redis中间件解决商品秒杀活动中出现的超卖问题(使用Java多线程模拟高并发环境)
一.引入Jedis依赖 可以新建Spring或Maven工程,在pom文件中引入Jedis依赖: <dependency> <groupId>redis.clients< ...
- redis高可用,保证高并发
目录 redis如何通过读写分离来承载读请求QPS超过10万+ redis replication以及master持久化对主从架构的安全意义 redis主从复制原理.断点续传.无磁盘化复制.过期key ...
- Redis的高并发、持久化、高可用架构设计
就是如果你用redis缓存技术的话,肯定要考虑如何用redis来加多台机器,保证redis是高并发的,还有就是如何让Redis保证自己不是挂掉以后就直接死掉了,redis高可用 我这里会选用我之前讲解 ...
- 2020重新出发,NOSQL,redis高并发系统的分析和设计
高并发系统的分析和设计 任何系统都不是独立于业务进行开发的,真正的系统是为了实现业务而开发的,所以开发高并发网站抢购时,都应该先分析业务需求和实际的场景,在完善这些需求之后才能进入系统开发阶段. 没有 ...
- redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: 断开的管道 (Write failed)
昨晚,包发到测试环境中,出现redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: 断开的 ...
- jedis使用管道(pipeline)对redis进行读写(使用hmset、hgetall测试)
一般情况下,Redis Client端发出一个请求后,通常会阻塞并等待Redis服务端处理,Redis服务端处理完后请求命令后会将结果通过响应报文返回给Client.这有点类似于HBase的Scan, ...
- redis客户端--jedis
一.jedis jedis 是 redis推荐的java客户端.通过Jedis我们可以很方便地使用java代码的方式,对redis进行操作.jedis使用起来比较简单,它的操作方法与redis命令相类 ...
随机推荐
- JQuery Mobile - 导航栏选中状态代码
class="ui-btn-active" 参考: https://wizardforcel.gitbooks.io/w3school-jqmobile/content/8.htm ...
- Dapper实现一对多对象关系聚合导航属性
领域对象:Game(游戏), Room(游戏群),两者一对多的关系,SQL语句中会用到JOIN public class Game : AggregateRoot { public string Ta ...
- ICMP与ping:投石问路的侦察兵
1. ICMP 协议 ICMP全称Internet Control Message Protocol,就是互联网控制报文协议.ping命令就是基于它工作的. ICMP 报文是封装在 IP 包 里面的. ...
- Tools - Others
01 - 一些网络工具 文档查阅 https://devdocs.io/ API文档 http://overapi.com/ 开源代码及文档搜索 https://searchcode.com/ 电子书 ...
- golang 切片和数组在for...range中的区别
切片是引用类型,而数组是值类型,并且for...range有以下规则: range表达式只会在for语句开始执行时被求值一次,无论后边会有多少次迭代 range表达式的求值结果会被复制,也就是说,被迭 ...
- 【sping揭秘】11、Java 平台上的AOP实现机制
动态代理 Jdk1.3只有引入的动态代理机制,可以再运行期间,为相应的接口(必须得有接口)动态生成对应的代理对象 基于以上问题,我们可以将横切关注点逻辑封装到动态代理的invocationhandle ...
- easyui datebox 只选择月份的方法
easyui datebox 只选择月份的方法 效果如下图: 代码如下: <html > <head> <meta charset="utf-8"&g ...
- odoo开发笔记 -- 用户配置界面如何增加模块访问权限
在odoo设置界面,点击用户,进入用户配置界面,会看到: 访问权 | 个人资料菜单 在访问权 page菜单界面,可以看到系统预制的一些模块都会显示在这里, 那么,我们自己开发的模块如何显示在这块呢,从 ...
- VM虚拟机装centos无法自动获取IP的解决方法
在虚拟机中使用ip addr 查看网卡 可以看到这个ens33,可能每台机器的名称不一样 然后找到/etc/sysconfig/network-scripts/ifcfg-eth33 编辑此文件 vi ...
- Word在转PDF的过程中如何创建标签快速方便阅读(图文详解)
不多说,直接上干货! 选择如下 成功! 欢迎大家,加入我的微信公众号:大数据躺过的坑 人工智能躺过的坑 同时,大家可以关注我的个人博客: http://www.cnbl ...