redis使用场景_Redis常见的工作场景使用实战,Redisson分布式锁的实现

迎关注我的头条号: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实现购物车功能:
例如:

051568a99fae347ff979dee488a36b12.png

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订阅号推送,微博推送

d87be9bee7fbc2a4066104b49dd36df1.png

代码实现:

    @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脚本就不会,他把两个步骤合成一个步骤去执行,这样保证原子性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值