Redis一些常用的技术

发布时间:2023年12月18日


第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 或者 debt
        transaction.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;
    }
    @Override
    public 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 then
    redis.call('set',KEYS[1],count-b)
    return redis.call('get', KEYS[1])
end
---End

在这里插入图片描述


文章来源:https://blog.csdn.net/2301_77225918/article/details/135064835
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。