您现在的位置是:首页 >其他 >redis(3)网站首页其他

redis(3)

每天想要幸福一点点 2024-06-02 12:00:03
简介redis(3)

redis客户端登陆:

redis-cli -h host -p port -a password

String类型的应用场景:

1)String通常用于保存单个字符串或者JSON格式的字符串数据

2)因为String类型通常是二进制安全的,因此你完全可以把一个图片内容当作字符串来进行存储

3)计数器,是常规的key-value缓存应用,常规计数,微博粉丝数

因为Incrby等指令本身就有原子操作的特性,所以我们完全可以利用redis的incr,incrby,decr,decrby等指令来实现原子计数的效果,假设说在某一种情况下3个客户端同时读取了num的值为1,那么这三个客户端同时针对num的值进行了+1的操作,那么最终这个num的值一定是5,不少网站都利用redis的这个特性来实现业务上的统计计数请求,不仅读写性能高,而且线程安全

Hash类型的应用场景:频繁对存储的对象进行增删改查

hash类型特别适用于存储对象数据,还常常用于存储一个对象或者是分布式session相比较于string类型而言,将一个对象存储到hash类型中要比存储在sring类型中要占用更少的内存空间,特别适用于存储对象的信息,还可以很方便的针对对象中的属性做增删改查,例如你要是用redis中的string类型来存储一个对象,那么就需要将JAVA中的Bean对象转化成一个JSON格式的字符串

key:product:user:1,value:对象的json格式字符串

上面的五个步骤不是一个原子操作,会产生线程安全问题 

hash是最接近于关系数据库结构的数据类型,我们可以将数据库中的一套记录或者是一个对象转化成HashMap存储在redis中,把用户ID当作是查找的key,存储的value对象包括姓名,年龄,生日等信息,如果使用普通的key-value进行存储,主要是有下面两种存储方式:

1)第一种方式就是将用户ID作为查找的key,将其他信息封装成一个对象以序列化的方式来进行存储,这种方式的缺点是,增加了序列化和反序列化的开销,并且需要修改其中一项信息的时候,就需要将整个对象进行访问并且修改操作需要对并发进行保护,引入线程安全问题

2)第二种方法就是将用户信息对象有多少个成员就存放多少个key-value键值对,使用用户ID+对应属性的名称作为唯一标识来取得最终属性的值,虽然省去了序列化开销和并发问题,但是用户ID重复进行存储,内存空间浪费很大

所以redis中的hash很好地解决了这个问题,redis中的hash实际上时内部存储的value作为一个HashMap,并且直接存储了这个Map成员的接口

手机验证码的操作:

1)用户在客户端发送手机号,点击发送之后随机生成四位验证码,有效期为60s,输入验证码点击验证,返回成功或者失败

2)当后端收到用户发送过来的手机号,首先要生成key值,形式为key=phone:number:手机号码

3)生成key值之后,我们会首先查询这个key是否在redis中存在,如果不存在,并针对key进行赋值,并且设置过期时间是60s,如果当前的key已经在redis中存在了,那么系统就直接进行提示,验证码已经发送还在有效期内,请打开手机查看验证码

Controller
@Slf4j
public class UserController {
    public  int GetRandomCode(){
        int code=(int)(Math.random()*10000);
        return code;
    }
    @Autowired
    private StringRedisTemplate template;
    @RequestMapping("/GetCode")
    @ResponseBody
    public Object GetCode(@RequestParam("PhoneNumber") String PhoneNumber){
        ValueOperations<String,String> options=template.opsForValue();
        //1.先生成验证码
        int RandomCode=GetRandomCode();
        //2.生成key
        String key="phone:code:"+PhoneNumber;
        //3.在redis中进行查询
        if(!template.hasKey(key)){
            String value= String.valueOf(RandomCode);
            options.set(key,value,60, TimeUnit.SECONDS);
            log.info("短信验证码已经存储到redis里面,验证码是",RandomCode);
            return "验证码已经发送成功,请查看手机";
        }else{
            return "发送吗之前已经发送过了,请耐心等待"+options.getOperations().getExpire(key);
        }

    }
}
@RequestMapping("/login")
    @ResponseBody
    public Object login(@RequestParam("PhoneNumber") String PhoneNumber) {
        ValueOperations<String,String> options=template.opsForValue();
        //1.先生成key值
        String key="phone:code:"+PhoneNumber;
        //2.查询key值在redis中是否存在
        if(template.hasKey(key)){
            //3.清空redis节省空间
            template.delete(key);
            return"手机号和验证码校验成功,登陆成功";
        }
        return "验证码错误或者手机号错误";
    }

4)为了防止用户恶意攻击,我们做出,每一个IP地址在5分钟内最多发送三次验证码,如果在5min内频繁发送验证码超过三次,那么直接给出相应的信息提示,并且直接索死用户12小时

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。