迎关注我的头条号:Wooola,10 年 Java 软件开发及架构设计经验,专注于 Java、Go 语言、微服务架构,致力于每天分享原创文章、快乐编码和开源技术。

前言

本项目基于springboot+ spring-boot-starter-data-redis+redisson

简单的redis demo可以参考:SpringBoot整合redis

https://www.jianshu.com/p/8e71737a1101

github地址:

Redisson:https://github.com/weiess/redis-and-Redisson.git

源码地址:https://github.com/weiess/redis-and-Redisson.git

redis大家工作的时候都很多,笔者根据自己经验总结下redis的几个数据类型,常用场景,也欢迎大家留言总结自己的经验。

hash

hash在redis里可以存储对象,当然string也可以,只不过hash相比较string,效率更高一点,而且功能也很强大,可以实现简单的购物车:
下面先给大家看下简单的存储对象hash实现:

/*    *   hash实现存储对象    * */    @Test    public void testHsetpojo(){        User user = new User();        user.setId(123);        user.setAge(20);        user.setAddr("北京");        user.setName("yang");        Map map = BeanUtils.beanToMap(user);        String key = "user";        redisUtil.hmset(key,map);        System.out.println(redisUtil.hmget(key));        System.out.println("id="+redisUtil.hget(key,"id"));        String key2 = "user:"+user.getId();        redisUtil.hmset(key2,map);        System.out.println(redisUtil.hmget(key2));    }

这里的redisUtil是笔者封好的工具类,源码在文章最底下。

hash存储对象的时候可以把user当作key,例如代码中的key,因为hash是 key item value三种结构,可以把后面的item和value看成一个map,这样结构就是key map,方便理解。

实际项目中可以给key加个标示符,比如key = userId:a123456,这个大家可以根据项目来定义。

可以用hash实现购物车功能:
例如:

hash.jpg

代码如下:

    /*     *   hash实现购物车     * */    @Test    public  void testcar(){        String key ="carUser:123456";        redisUtil.del(key);        Map map = new HashMap();        map.put("book:a11111",1);        map.put("book:a11112",2);        map.put("book:a11113",3);        boolean b = redisUtil.hmset(key,map);        System.out.println("key = "+redisUtil.hmget(key));        //增加book:a11111的数量        redisUtil.hincr(key,"book:a11111",1);        System.out.println(redisUtil.hmget(key));        //减少book:a11112的数量        redisUtil.hincr(key,"book:a11112",-3);        //或者redisUtil.hdecr(key,"book:a11111",1);        System.out.println(redisUtil.hmget(key));        //获取所有key1的field的值        System.out.println("hegetall="+redisUtil.hmget(key));        //获取key下面的map数量        System.out.println("length="+redisUtil.hlen(key));        //删除某个key下的map        redisUtil.hdel(key,"book:a11112");        System.out.println(redisUtil.hmget(key));    }

hash里的key就是当前用户的购物车,map就是商品(map里的key是商品id,map的v是数量)
功能实现注释都有。注意这里的减操作是可以为负数的,所以大家一定要注意判断负数的情况。

list

常见的list可以分为下面三个数据结构方便大家理解:

stack(栈)= LPUSH + LPOP Queue(队列)= LPUSH + RPOP BlockingMQ(阻塞队列)= LPUSH + BRPOP

    @Test    public void testList(){        String key = "a123456";        redisUtil.del(key);        String v1 = "aaaaa";        String v2 = "bbbbb";        String v3 = "ccccc";        List list = new ArrayList();        list.add(v1);        list.add(v2);        list.add(v3);        boolean b1 = redisUtil.lSet(key,list);        System.out.println(redisUtil.lGet(key,0,-1));        System.out.println(redisUtil.lGetIndex(key,0));        System.out.println(redisUtil.lpop(key));        System.out.println(redisUtil.rpop(key));        System.out.println(redisUtil.lGet(key,0,-1));        redisUtil.del(key);        redisUtil.rpush(key,v1);        System.out.println(redisUtil.lGet(key,0,-1));        redisUtil.rpush(key,v2);        System.out.println(redisUtil.lGet(key,0,-1));        redisUtil.lpush(key,v3);        System.out.println(redisUtil.lGet(key,0,-1));    }

实际工作中常用于消息推送,比如vx订阅号推送,微博推送

代码实现:

    @Test    public void testVX(){        String key = "VXuser:a123456";        redisUtil.del(key);        String message1 = "a1";        String message2 = "b2";        String message3 = "c3";        //订阅号a发表了一片文章,文章id是a1        redisUtil.lpush(key,message1);        //订阅号b发表了一片文章,文章id是b2        redisUtil.lpush(key,message2);        //订阅号b发表了一片文章,文章id是c3        redisUtil.lpush(key,message3);        //用户获取        System.out.println(redisUtil.lGet(key,0,-1));    }

比如user:a23456订阅了这个订阅号a,订阅号a写了一片内容,只需要加入user:a123456的队列中,user就能查看到,这里的redisUtil.lGet(key,0,-1)表示获取key下的所有v。

set

set常用于一些数学运算,他有求交集,并集,差集的功能:

    @Test    public void testset(){        String key1 = "a1";        redisUtil.del(key1);        String key2 = "a2";        redisUtil.del(key2);        redisUtil.sSet(key1,1,2,3,4,5);        System.out.println("key1="+redisUtil.sGet(key1));        redisUtil.sSet(key2,1,2,5,6,7);        System.out.println("key1="+redisUtil.sGet(key2));        //获取key的数量        System.out.println("length="+redisUtil.sGetSetSize(key1));        //取key1和key2的交集        System.out.println("交集="+redisUtil.sIntersect(key1,key2));        //取key1和key2的差集        System.out.println("差集="+redisUtil.sDifference(key1,key2));        //取key1和key2的并集        System.out.println("并集="+redisUtil.sUnion(key1,key2));        //取key1的随机一个数        System.out.println("随机数="+redisUtil.sRandom(key1));        System.out.println("key1="+redisUtil.sGet(key1));        //取key1的随机一个数,并且这个值在key中删除        System.out.println("随机数="+redisUtil.spop(key1));        System.out.println("key1="+redisUtil.sGet(key1));    }

实际工作中可以实现抽奖,共同关注,推荐好友等功能:

     @Test    public void testSet2(){        String key ="act:123456";        redisUtil.del(key);        long l = redisUtil.sSet(key,"a1","a2","a3","a4","a5");        System.out.println(redisUtil.sGet(key));        //抽奖        System.out.println(redisUtil.spop(key));        String user1 = "vxuser:a123456";        String user2 = "vxuser:b123456";        String user3 = "vxuser:c123456";        String user4 = "vxuser:d123456";        String user5 = "vxuser:e123456";        String user6 = "vxuser:f123456";        redisUtil.del("gzuser1");        redisUtil.del("gzuser2");        //gzuser1关注user2,user3,user6        redisUtil.sSet("gzuser1",user2,user3,user6);        //gzuser2关注user1,user3,user4,user5        redisUtil.sSet("gzuser2",user1,user3,user4,user5);        //共同好友        System.out.println("共同好友"+redisUtil.sIntersect("gzuser1","gzuser2"));        //你关注的好友也关注了他        Set set = redisUtil.sUnion(user1,user2);        //这里取并集,放在中间表bj里        for (String s:set){            redisUtil.sSet("bj",s);        }        System.out.println(redisUtil.sGet("bj"));        System.out.println("你关注的好友也关注了他"+redisUtil.sDifference("bj","gzuser1"));    }

zset

zset相比较set一个有序,一个无序,具体功能大同小异,我就不多说。

string

简单的string基本功能我就不多说了,这里要说的是分布式常见的setnx命令实现分布式锁:

setnx命令其实表示『SET if Not eXists』(如果不存在,则 SET)的简写。设置成功,返回 1 ;设置失败,返回 0 。
如果set 的key已经在redis里了,你再setnx,就会失败,但是你继续用set命令,是会覆盖当前的key,且返回成功。

/*    *   setnx 实现最简单的分布式锁    * */    @Test    public void setlock() {        DefaultRedisScript script = new DefaultRedisScript();        script.setScriptSource(new ResourceScriptSource(new ClassPathResource("lua/deleteLua.lua")));        script.setResultType(Long.class);        String key ="product:001";        String value = Thread.currentThread().getId()+"";        try {            boolean result = redisUtil.setnx(key,value,100);            if(!result){                System.out.println("系统繁忙中");            } else {                System.out.println("这里是你业务代码");            }        }catch (Exception e){            e.printStackTrace();        }finally {            Object result = redisUtil.execute(script,Collections.singletonList(key),value);            System.out.println(result);//            if (value.equals(redisUtil.get(key))){//                redisUtil.del(key);            }        }    }

这是最简单的分布式锁实现,我给大家简单解释下:
首先,DefaultRedisScript这个类是为了读取lua脚本,这里笔者的finally代码块用了lua脚本删除redis的key,其实

Object result = redisUtil.execute(script,Collections.singletonList(key),value);

这行代码等价于下面这行代码

 if (value.equals(redisUtil.get(key))){          redisUtil.del(key); }

为什么要用lua脚本呢,更多的是为了原子性,如果用if操作,要执行两部,在大型的环境下很容易出问题,而lua脚本就不会,他把两个步骤合成一个步骤去执行,这样保证原子性。

hash redis springboot_Redis常见的工作场景使用实战,Redisson分布式锁的实现相关推荐

  1. Redis实战——Redisson分布式锁

    目录 1 基于Redis中setnx方法的分布式锁的问题 2 Redisson 2.1 什么是Redisson 2.2 Redisson实现分布式锁快速入门 2.3 Redisson 可重入锁原理 什 ...

  2. Redis:Redisson分布式锁的使用(推荐使用)

    Redis:Redisson分布式锁的使用(生产环境下)(推荐使用) 关键词 基于NIO的Netty框架,生产环境使用分布式锁 redisson加锁:lua脚本加锁(其他客户端自旋) 自动延时机制:启 ...

  3. Redis进阶- Redisson分布式锁实现原理及源码解析

    文章目录 Pre 用法 Redisson分布式锁实现原理 Redisson分布式锁源码分析 redisson.getLock(lockKey) 的逻辑 redissonLock.lock()的逻辑 r ...

  4. redis redisson 分布式锁 WRONGTYPE Operation against a key holding the wrong kind of value

    在使用redisson加锁的时候报错如下 trylock WRONGTYPE Operation against a key holding the wrong kind of value 错误场景: ...

  5. SpringBoot实战实现分布式锁一之重现多线程高并发场景

    实战前言:上篇博文我总体介绍了我这套视频课程:"SpringBoot实战实现分布式锁" 总体涉及的内容,从本篇文章开始,我将开始介绍其中涉及到的相关知识要点,感兴趣的小伙伴可以关注 ...

  6. 用分布式锁来防止库存超卖,但是是每秒上千订单的高并发场景,如何对分布式锁进行高并发优化来应对这个场景?

    用分布式锁来防止库存超卖,但是是每秒上千订单的高并发场景,如何对分布式锁进行高并发优化来应对这个场景? 转载 codeing_doc 最后发布于2018-11-23 09:44:41 阅读数 1073 ...

  7. redis ,redisson 分布式锁深入剖析

    目录 为什么要用分布式锁? 分布式锁所遵循的原则? redis 分布式锁 redis 原始分布式锁实现 加锁 释放锁 redis 分布式锁存在的问题 redisson  实现分布式锁 redisson ...

  8. Redisson分布式锁实战(适用于Redis高并发场景)

    实现方式一:存在抛异常后lock值无法归0的问题 @Autowired private StringRedisTemplate stringRedisTemplate;@RequestMapping( ...

  9. 顶级“Redis学习笔记”,缓存雪崩+击穿+穿透+集群+分布式锁,NB了

    如果你是一位后端工程师,面试时八成会被问到 Redis,特别是那些大型互联网公司,不仅要求面试者能简单使用 Redis,还要深入理解其底层实现原理,具备解决常见问题的能力.可以说,熟练使用 Redis ...

最新文章

  1. 关于CENTOS6.X下修改网卡名称的方法
  2. 笔记-项目范围管理-工作说明书与项目范围说明书的区别
  3. WebLogic下载地址
  4. 支持Windows 7的CAD—AutoCAD Civil 3D 2010
  5. app把信息添加到mysql_如何将数据库表中的数据添加到ListView C#Xamarin Android App
  6. lambda 使用_如何使用Lambda和API网关构建API
  7. 778. 水位上升的泳池中游泳
  8. python动态变量名_python实现可变变量名方法详解
  9. 频率分布直方图组距如何确定_频率分布有关的概念
  10. HttpRunnerManager接口自动化测试框架在win环境下搭建教程
  11. C#中Socket用法,多个聊天和单一聊天。
  12. ORACLE 9 默认密码
  13. EmguCv模板匹配学习日记
  14. 对计算机科学的总体认识,浅谈对计算机科学与技术的认识
  15. 2022年证券大宗交易研究报告
  16. Detach Procedure
  17. 论文笔记:HIE-SQL:History Information Enhanced Network for Context-Dependent Text-to-SQL Semantic Parsing
  18. rtmp断线重连_rtsp转rtmp rtsp2rtmp 同时16路视频 rtmp推流器 支持ipc dvr nvr
  19. Settings Preference 的理解
  20. Android两个app间跳转-deepLink的使用

热门文章

  1. 如何使用代码创建service contract并实现partner determination
  2. SAP WebIDE 是如何加载SAP UI5里自定义的XML view的 - JerryMaster.view.xml
  3. 处理SAP gateway service使用过程中遇到的400 error - Malformed URI literal syntax
  4. PHP CLI应用的调试原理
  5. 使用javap分析Java的字符串操作
  6. 如何使用SAP CRM Marketing Survey创建一个市场问卷调查
  7. paraView做动画(终极教程)
  8. php代码执行相关函数,关于当前PHP脚本运行时系统信息相关函数
  9. 一个点是否在矩形内的算法_478,回溯算法解单词搜索
  10. 二维碰撞检测matlab,二维平面内的碰撞检测【二】