Redis实战

1.RedisTempla使用Scan

@Component
public class ScanDemo {

    @Autowired
    private StringRedisTemplate redisTemplate;


    public void test() {

       
        for (int i = 0; i < 100; i++) {
            redisTemplate.opsForValue().set("b" + i, "1");
        }
        ScanOptions scanOptions = ScanOptions.scanOptions().match("b*").count(2).build();
        Cursor<String> cursor = redisTemplate.scan(scanOptions);

        while (cursor.hasNext()){
            System.out.println(cursor.next());
        }

        cursor.close();

    }
}




Java

2.lua脚本操作Redis

一次扣减一个商品库存

@Component
public class LuaDemo {

    @Autowired
    private StringRedisTemplate redisTemplate;


    public void test() {

      List<String> keys = new ArrayList<>();
        keys.add("yanjie007");

        String lua = "return redis.call('set',KEYS[1],ARGV[1])";

        RedisScript<String> redisScript=  RedisScript.of(lua,String.class);

        String shuai = stringRedisTemplate.execute(redisScript, keys, "今天真帅");

        System.out.println(shuai);

    }
}

  //扣减库存 @Test
    void test2() throws IOException {
        valueOperations.set(key,15L);
        StringBuilder sb = new StringBuilder();
        sb.append(" local key = KEYS[1]  ");
        sb.append(" local qty = ARGV[1]  ");
        sb.append(" local redis_qty = redis.call('get',key)  ");
        sb.append(" if tonumber(redis_qty) >= tonumber(qty) then  ");
        sb.append("   redis.call('decrby',key,qty) ");
        sb.append("  return  -1  ");
        sb.append(" else  ");
        sb.append("  return tonumber(redis_qty) ");  //  0, 1,2,3 ....
        sb.append(" end  ");
        sb.append("   ");
        RedisScript<Long> script = RedisScript.of(sb.toString(),Long.class);
        ExecutorService executorService = Executors.newCachedThreadPool();

        for (int i = 1; i <= 10; i++) {
            int finalI = i;
            executorService.execute(()->{
                int needQty = RandomUtil.randomInt(1, 5);
                Long qty =  stringRedisTemplate.execute(script, CollUtil.newArrayList(key), needQty+"");
             if(qty.intValue() == -1 ){
                 System.out.println("线程"+ finalI +"扣减成功,需求量是:"+needQty);
              } else {

                 System.out.println("线程"+ finalI +"扣减失败,当前库存变量是:"+qty);
             }
            });
        }


        System.in.read();
    }


Java

一次扣减多个商品的库存

void test4()  {

        StringBuilder sb = new StringBuilder();
        sb.append(" local table = {}  "); // 你要扣减的key :product.1
        sb.append(" local values =  redis.call('mget',  unpack(KEYS) )"); // [product.1,product.2]   =>  product.1 product.2
        sb.append(" for i = 1, #KEYS   do  ");
        sb.append("   if  tonumber(ARGV[i]) > tonumber(values[i])   then ");
        sb.append("     table[#table + 1] =  KEYS[i] .. '=' .. values[i] "); // product.1=23
        sb.append("   end ");
        sb.append(" end ");
        sb.append(" if #table > 0 then ");
        sb.append("   return table  ");
        sb.append(" end ");
        sb.append(" for i = 1 , #KEYS do ");
        sb.append("   redis.call('decrby',KEYS[i],ARGV[i])  ");
        sb.append(" end ");
        sb.append(" return {} ");
        RedisScript<List> luaScript = RedisScript.of(sb.toString(), List.class);

          List<StockProduct> stockProducts =  new ArrayList<>();
          stockProducts.add(new StockProduct(5,1));
          stockProducts.add(new StockProduct(4,2));

        List<String> keys = stockProducts.stream().map(it -> "product." + it.getId()).collect(Collectors.toList());
        Object[] qtys = stockProducts.stream().map(it -> it.getQty() + "").toArray();
        List<String> list = stringRedisTemplate.execute(luaScript,
                keys,
                qtys);
        if(list.isEmpty()){
            System.out.println("库存冻结成功");
        } else {

            for (String key_qty : list) {
                String[] split = key_qty.split("=");
                System.out.println(split[0] + "库存不足,剩余库存量:" + split[1]);
            }

        }


        ThreadUtil.safeSleep(3000);

    }

Java

3.模拟多线程并发使用Decrby

@Component
public class DecrByDemo {

    @Resource(name = "redisTemplate")
    private ValueOperations<String, Integer> valueOperations;

    private static final String key = "product.01";

    public void test() throws InterruptedException {

        valueOperations.set(key, 5);

        ExecutorService executorService = Executors.newCachedThreadPool();

        for (int i = 0; i < 10; i++) {
            executorService.execute(() -> {

                Integer value = valueOperations.get(key);
                if (value >= 1) {
                    valueOperations.set(key, value - 1);
                    System.out.println(StrUtil.format("线程{} -> 扣减成功", Thread.currentThread().getName()));
                } else {
                    System.out.println(StrUtil.format("线程{} -> 扣减失败", Thread.currentThread().getName()));

                }

            });
        }

       Thread.sleep(10*1000);
    }

    public void test2() throws InterruptedException {



        valueOperations.set(key, 5);

        ExecutorService executorService = Executors.newCachedThreadPool();

        for (int i = 0; i < 10; i++) {
            executorService.execute(() -> {

                Long value = valueOperations.decrement(key);
                if (value >= 0) {

                    System.out.println(StrUtil.format("线程{} -> 扣减成功,剩余库存{}", Thread.currentThread().getName(),value));
                } else {
                    System.out.println(StrUtil.format("线程{} -> 扣减失败", Thread.currentThread().getName()));

                }

            });
        }

        Thread.sleep(10*1000);
    }
}

Java

4.模拟多线程并发获取分布式锁SetNX

@Component
public class SetNxDemo {

    @Resource(name = "redisTemplate")
    private ValueOperations<String, String> valueOperations;

    private static final String key = "product.1";

    public void test() throws InterruptedException {

      //出入库场景 商品1

        ExecutorService executorService = Executors.newCachedThreadPool();

        for(int i =1; i<6;i++){

            executorService.execute(()->{
                // 获取分布式锁

                while (true){
                    Boolean b = valueOperations.setIfAbsent("product.1", "IO202303170929,"+ DateUtil.now());
                    if(b){
                        System.out.println(Thread.currentThread().getName() + " 获取到了分布式锁" );
                        ThreadUtil.safeSleep(5000); //模拟业务操作
                        stringRedisTemplate.delete("product.1");
                        break;
                    } else {
                        System.out.println(Thread.currentThread().getName() + " 获取锁失败" );
                        ThreadUtil.safeSleep(2000);
                    }

                }

            });
        }

       System.in.read();
    }

}



Java

5.BitMap模拟在线统计

@Component
public class BitMapDemo {

    @Resource(name = "redisTemplate")
    private ValueOperations valueOperations;



    @Autowired
    private StringRedisTemplate redisTemplate;

    private static final int user01 = 1;
    private static final int user02 = 2;
    private static final int user03 = 3;

    private static String key20220601 = "20200601";
    private static String key20220602 = "20200602";
    private static String key20220603 = "20200603";
    private static String saveKey = "20200601#20200602#20200603";

    public void test() {

        valueOperations.setBit(key20220601, user01, true);
        valueOperations.setBit(key20220601, user02, true);


        valueOperations.setBit(key20220602, user02, true);


        valueOperations.setBit(key20220603, user01, true);
        valueOperations.setBit(key20220603, user03, true);


        //1. 一直在线人数统计
        //2. 时间段活跃用户
        RedisCallback<Long> callback = connection -> {
            return connection.bitOp(RedisStringCommands.BitOperation.AND, saveKey.getBytes(),
 key20220601.getBytes(), key20220602.getBytes(), key20220603.getBytes());
        };
        Long value = redisTemplate.execute(callback);
        RedisCallback<Long> callback2 = connection -> {
            return connection.bitCount(saveKey.getBytes());
        };
        Long value2 = redisTemplate.execute(callback2);
        System.out.println(value2);
    }

}




Java







相关推荐

  1. Redis实战

    2024-04-03 10:00:07       6 阅读
  2. Redis 实战缓存

    2024-04-03 10:00:07       26 阅读
  3. Redis-实战案例

    2024-04-03 10:00:07       32 阅读
  4. docker实战:安装redis

    2024-04-03 10:00:07       31 阅读

最近更新

  1. websocket消息处理失败排查(redis大key)

    2024-04-03 10:00:07       0 阅读
  2. Golang:字符串正则匹配的简单使用

    2024-04-03 10:00:07       0 阅读
  3. PostCSS概述

    2024-04-03 10:00:07       0 阅读
  4. 帮我一下,c++

    2024-04-03 10:00:07       0 阅读
  5. C#:直接调用 OpenFileDialog

    2024-04-03 10:00:07       0 阅读
  6. 第二章:c语言中的表达式和运算符

    2024-04-03 10:00:07       0 阅读
  7. Vue解构工作原理

    2024-04-03 10:00:07       0 阅读
  8. python项目环境安装实测

    2024-04-03 10:00:07       0 阅读
  9. 3、完成量

    2024-04-03 10:00:07       0 阅读

热门阅读

  1. Pathlib库的有哪些神奇功能在Python中

    2024-04-03 10:00:07       5 阅读
  2. 速盾:cdn加速https额外收费吗?

    2024-04-03 10:00:07       6 阅读
  3. pytorch | yolov5 Can not get arrribute SiLU

    2024-04-03 10:00:07       5 阅读
  4. 常见哈希算法及其应用场景

    2024-04-03 10:00:07       5 阅读
  5. 设计模式(14):命令模式

    2024-04-03 10:00:07       5 阅读
  6. 1344: 【递推】【入门】流感传染

    2024-04-03 10:00:07       6 阅读
  7. WebKit内核架构深度解析:核心技术与工作机制

    2024-04-03 10:00:07       6 阅读
  8. web有哪些方式可以实时更新数据

    2024-04-03 10:00:07       7 阅读
  9. vue 基础回顾

    2024-04-03 10:00:07       5 阅读
  10. 【2024最新】vue3的基本使用(超详细)

    2024-04-03 10:00:07       6 阅读
  11. freertosday3

    2024-04-03 10:00:07       4 阅读
  12. 平台介绍-大屏组件

    2024-04-03 10:00:07       5 阅读