文章目录
- 第1关:Redis 事务与锁机制
- 第2关:流水线
- 第3关:发布订阅
- 第4关:超时命令
- 第5关:使用Lua语言
第1关:Redis 事务与锁机制
编程要求
根据提示,在右侧编辑器Begin-End补充代码,根据以下要求完成一个模拟一次银行卡支付扣款的流程:
1、当余额不足时,放弃所有被监控的键,返回false。
2、在余额扣除消费的金额,在支付金额里加上消费的金额。
测试说明
我会对你编写的代码进行测试:
测试输入:无;
预期输出:
支付成功
本次扣款10元,余额为90元
开始你的任务吧,祝你成功!
示例代码如下:
package com.test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
import java.util.List;
public class TestRedis {private static String host = "127.0.0.1";private static int port = 6379;private static Jedis jedis = new Jedis(host, port);public static boolean payMent(int deduction) throws InterruptedException {int balance; // 余额//设置余额金额jedis.set("balance", "100");jedis.set("deduction", "0");//监控扣款和余额jedis.watch("balance", "deduction");/***********Begin***********/balance = Integer.parseInt(jedis.get("balance"));// 余额不足if (balance < deduction) {jedis.unwatch(); // 放弃所有被监控的键System.out.println("对不起,你的余额不足");return false;}Transaction transaction = jedis.multi();// 扣钱transaction.decrBy("balance", deduction);Thread.sleep(5000); // 在外部修改 balance 或者 debttransaction.incrBy("deduction", deduction);// list为空说明事务执行失败List<Object> list = transaction.exec();return !list.isEmpty();/***********End***********/}public static void main(String[] args) throws InterruptedException {boolean resultValue = payMent(10);if (resultValue==true){System.out.println("支付成功");int balance = Integer.parseInt(jedis.get("balance"));int deduction = Integer.parseInt(jedis.get("deduction"));System.out.printf("本次扣款"+deduction+"元,余额为"+balance+"元");}else{System.out.println("支付失败");}jedis.close();}
}
第2关:流水线
编程要求
根据提示,在右侧编辑器Begin-End补充代码,按照以下要求开启一次流水线技术:
开启流水线。
测试十万条读写操作,设置 key 值为 key0 、 key1 、 key2 …key99998、key99999,对应 value 值为 value0 、value1、value2…value99998、value99999。
结束流水线。
测试说明
我会对你编写的代码进行测试:
测试输入:无;
预期输出:
开启流水线
消耗时间:XXX毫秒
关闭流水线
流水线成功完成!
开始你的任务吧,祝你成功!
示例代码如下:
package com.test;
import redis.clients.jedis.*;
import java.util.List;
public class RedisPipeline {public boolean pipeline() {String redisHost = "127.0.0.1";int redisPort = 6379;Jedis jedis = new Jedis(redisHost, redisPort);jedis.flushDB();/**********Begin**********/long start = System.currentTimeMillis();// 开启流水线Pipeline pipeline = jedis.pipelined();System.out.println("开启流水线");// 测试十万条读写操作for (int i = 0; i < 100000; i++) {pipeline.set("key"+i,"value"+i);pipeline.get("key"+i);}long end = System.currentTimeMillis();//关闭流水线pipeline.close();System.out.println("消耗时间:"+(end-start)+"毫秒");System.out.println("关闭流水线");/**********End**********/return true;}
}
第3关:发布订阅
编程要求
根据提示,在右侧编辑器Begin-End补充代码,按照以下要求:
在SubThread类中订阅指定频道redis。
测试说明
我会对你编写的代码进行测试:
测试输入:quit;
预期输出:
订阅redis, 订阅频道为 redis, 线程将被阻塞
订阅redis频道成功, 频道为 redis, 订阅频道为 1
请输入传输的信息:
关闭程序
开始你的任务吧,祝你成功!
示例代码如下:
package com.test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
public class SubThread extends Thread {private final JedisPool jedisPool;private final Subscriber subscriber = new Subscriber();private final String channel = "redis";public SubThread(JedisPool jedisPool) {super("SubThread");this.jedisPool = jedisPool;}@Overridepublic void run() {System.out.println(String.format("订阅redis, 订阅频道为 %s, 线程将被阻塞", channel));Jedis jedis = null;try {/************* Begin ***************/jedis = jedisPool.getResource();jedis.subscribe(subscriber, channel);/************* End ***************/} catch (Exception e) {System.out.println(String.format("订阅频道错误, %s", e));} finally {if (jedis != null) {jedis.close();}}}
}
第4关:超时命令
编程要求
根据提示,在右侧编辑器Begin-End补充代码,按照以下要求使用 Spring 操作 Redis 超时命令过程:
创建键值对:key 值为“今天你吃了吗?”
获取 key 值
设置 key 的过期时间为 5 秒
测试说明
我会对你编写的代码进行测试:
测试输入:无;
预期输出:
今天你吃了吗?
null
开始你的任务吧,祝你成功!
示例代码如下:
package com.redis;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.util.concurrent.TimeUnit;
public class OverTimeRedisTest {@SuppressWarnings({ "unchecked", "rawtypes", "resource" })public static void main(String[] args) {ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");RedisTemplate redisTemplate=applicationContext.getBean(RedisTemplate.class);redisTemplate.execute((RedisOperations ops) -> {/************Begin************/ops.boundValueOps("key").set("今天你吃了吗?");System.out.println(ops.boundValueOps("key").get());ops.expire("key",5L, TimeUnit.SECONDS);/************End************///睡眠6秒,使得key值过期try {Thread.sleep(6000);}catch (InterruptedException e){e.printStackTrace();}//获取key值System.out.println(ops.boundValueOps("key").get());//结束所有线程,退出系统System.exit(0);return null;});}
}
第5关:使用Lua语言
编程要求
根据提示,在右侧编辑器 Begin - End 处补充代码,根据以下要求完成一次手机销售库存的操作:
编写 ItemRedisTest.lua 文件,判断销售量是否比库存数量多,如果库存数量大于这次销售量,将新的库存数量更新到原来的 key 值上。
编写 ItemRedisTest.java 文件,使用 BufferedReader 读取ItemRedisTest.lua 文件,使用 eval 命令执行文件里的字符串,设置手机销售量为10。
ItemRedisTest.lua 地址为:/data/workspace/myshixun/step5/ItemRedisTest.lua
测试说明
我会对你编写的代码进行测试:
测试输入:无;
预期输出:
手机库存剩余:90
开始你的任务吧,祝你成功!
代码示例如下:
package com.redis;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import redis.clients.jedis.Jedis;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class ItemRedisTest {public static void main(String[] args) throws IOException {ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");RedisTemplate redisTemplate=applicationContext.getBean(RedisTemplate.class);Jedis jedis=(Jedis)redisTemplate.getConnectionFactory().getConnection().getNativeConnection();jedis.set("phone_item_stock", "100");/************Begin************/BufferedReader in= new BufferedReader(new FileReader("/data/workspace/myshixun/step5/ItemRedisTest.lua"));String context =null;String script="";while (null != (context = in.readLine())){script+=context+"\n";}Object obj = jedis.eval(script, 1,"phone_item_stock","10");/************End************/System.out.println("手机库存剩余:"+obj);//关闭连接jedis.close();System.exit(0);}
}
之后在命令行中输入下列代码:
vim /data/workspace/myshixun/step5/ItemRedisTest.lua
编辑该文件内容
local count = redis.call('get', KEYS[1])
local a=tonumber(count)
local b=tonumber(ARGV[1])
---Begin
if a>=b thenredis.call('set',KEYS[1],count-b)return redis.call('get', KEYS[1])
end
---End