欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 培训 > Redis实战(使用Scan,Lua脚本,一次扣多个库存,多线程并发使用,并发获取分布式锁,BItMap实现签到和在线统计)

Redis实战(使用Scan,Lua脚本,一次扣多个库存,多线程并发使用,并发获取分布式锁,BItMap实现签到和在线统计)

2024/11/30 15:36:23 来源:https://blog.csdn.net/zhzjn/article/details/142602059  浏览:    关键词:Redis实战(使用Scan,Lua脚本,一次扣多个库存,多线程并发使用,并发获取分布式锁,BItMap实现签到和在线统计)

1.使用Scan

2.lua脚本操作Redis

一次扣减一个商品库存

一次扣减多个商品的库存

 @Testvoid test100() {String  key = "product.1";stringRedisTemplate.opsForValue().set("product.1","10");stringRedisTemplate.opsForValue().set("product.2","20");stringRedisTemplate.opsForValue().set("product.3","30");}@Test //模拟下单扣多个商品库存void test3() {ArrayList<FreezeProduct> freezeProducts = CollUtil.newArrayList(new FreezeProduct().setProductId(1).setQty(5),new FreezeProduct().setProductId(2).setQty(5),new FreezeProduct().setProductId(3).setQty(5));StringBuilder sb = new StringBuilder();// 1. 我要知道需求量是多少 ,还要知道是哪个keysb.append("  local myTable = {} ");// 2. 我要判断目前的库存量是否满足需求量sb.append(" local redisQtys = redis.call('mget',unpack(KEYS)) ");sb.append(" for i = 1, #KEYS  do ");sb.append("    if tonumber(ARGV[i]) > tonumber(redisQtys[i])  then ");sb.append("        myTable[#myTable + 1] = KEYS[i] .. '=' .. redisQtys[i]  ");sb.append("     end ");sb.append(" end ");// 3. myTable 有元素  return  ,没有元素 就扣sb.append(" if #myTable > 0 then  ");sb.append("  return myTable ");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> script = RedisScript.of(sb.toString(),List.class);List<String> keys = freezeProducts.stream().map(it -> "product." + it.getProductId()).collect(Collectors.toList());Object[] qtys = freezeProducts.stream().map(it -> it.getQty() + "").toArray();List list = stringRedisTemplate.execute(script, keys,qtys);if(list.isEmpty()){System.out.println(StrUtil.format("下单成功"));} else {System.out.println(StrUtil.format("下单失败,{}",list));}}

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


public class DecrByDemo {@Resource(name = "redisTemplate")private ValueOperations<String, Integer> valueOperations;private static final String key = "product.01";public void test() {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()));}});}System.in.read();}public void test2() {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()));}});}System.in.read();}
}

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

@Component
public class SetNxDemo {@Resource(name = "redisTemplate")private ValueOperations<String, String> valueOperations;public void test() throws InterruptedException {//出入库场景 ExecutorService executorService = Executors.newCachedThreadPool();for(int i =1; i<6;i++){executorService.execute(()->{while (true){// 获取分布式锁Boolean b = valueOperations.setIfAbsent("wms.io.locker",  DateUtil.now());if(b){System.out.println(Thread.currentThread().getName() + " 获取到了分布式锁" );ThreadUtil.safeSleep(5000); //模拟业务操作stringRedisTemplate.delete("wms.io.locker");break;} else {System.out.println(Thread.currentThread().getName() + " 获取锁失败,睡眠2s" );ThreadUtil.safeSleep(2000);}}});}System.in.read();}}

5.BitMap

签到

@Component
public class BitMapDemo {@Autowiredprivate StringRedisTemplate stringRedisTemplate;private final  String key ="sign.2024.zhouxingxing";public void test(){//设置签到stringRedisTemplate.opsForValue().setBit(key,2,true);stringRedisTemplate.opsForValue().setBit(key,85,true);//获取周星星同学的签到天数RedisCallback<Long> callback = connection -> { return  connection.bitCount(key.getBytes(),0,365);};Long count = stringRedisTemplate.execute(callback);//打印周星星2024年签到天数System.out.println("周星星2024年一共签到天数:"+count);}
}

模拟在线统计

@Component
public class BitMapDemo {@Resource(name = "redisTemplate")private ValueOperations valueOperations;@Autowiredprivate 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 = "q1";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);}}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com