Redis介绍(数据类型+应用场景)

本文详细介绍了Redis的基础知识和应用场景,包括String、Hash、List、Set、Zset五种数据类型及其用途。Redis作为高性能的内存数据库,常用于缓存热点数据、实现限时业务、计数限流、排行榜、分布式锁、消息队列等多种场景。同时,文中还讨论了Redis的单线程模型、数据库管理和命令执行顺序等核心概念。
摘要由CSDN通过智能技术生成


前言

  • 参考多篇优秀文章,结合自己实践,写下该文

一、Redis

  • 开源的
  • 使用C语言编写
  • 高性能基于内存运行的
  • 非关系型数据库NoSql
  • Key-Value数据库

二、数据类型

  • 相比于其它的缓存,支持丰富的数据类型

1、String

  • 字符串,string类型是二进制安全的,所以redis的string 可以包含任何数据,比如jpg图片、序列化的对象

2、Hash

  • 散列,相当于 HashMap
  • 是一个string类型的 field 和 value 的映射表
  • 适合存储一些结构化的数据,如登录用户信息
    {
        //key=1,userId
        1:{
            //hashKey=name,value=kimi
            name: kimi
            age: 18,
            address: bj
        }
    }
    

3、List

  • 列表,相当于LinkedList
  • 底层是通过链表来实现的,所以对于list来说首尾添加、删除 操作很快,但索引定位非常慢
  • 可以利用它来实现一个栈、队列

4、Set

  • 无序集合,不可重复,相当于 HashSet

5、Zset

  • 有序集合,不可重复
  • 不是先添加的在前面,后添加的在后面
  • 每个元素都会关联一个double类型的分数,通过分数来为集合中的成员进行从小到大排序

三、基础知识

  • Redis是单进程单线程的网络模型,用的是epoll网络模型,网络模型都是单线程异步非阻塞处理网络请求
  • Redis默认拥有16个数据库,并且每个数据库的数据是隔离的不能共享,不支持自定义数据库的名字,每个数据库都以编号命名db1,数据库编号从0开始,默认使用db0数据库;集群就没有数据库的概念,集群模式下只有一个db0,可以将项目名称做为该项目所有redis的key前缀,以避免多个项目共用一个redis存在key一样的情况,便于管理:项目名:业务名:key
  • 多个数据库之间并不是完全隔离的,比如FLUSHALL命令可以清空一个Redis实例中所有数据
    库中的数据,所以说这些db更像是命名空间,且不适宜存储不同应用程序的数据
  • Redis提供的所有API操作,相对于服务端方面都是one by one执行的,命令是一个接着一个执行的,不存在并行执行的情况

四、Redis应用场景

1、热点数据的缓存

  • 由于redis访问速度快,很适合用来存储热点数据,例如 热点商品、热点信息(明星出轨)等访问量较高的数据

2、限时业务的运用

  • redis中可以使用expire设置一个key的生存时间,到时间后会删除它,利用这一特性可以运用在限时的优惠活动信息、手机验证码等

3、计数、限流相关问题

  • redis种的增量increment可以实现原子性的递增,可以运用于高并发的秒杀活动、分布式序列号的生成、具体业务,比如限制一个手机号发多少条验证码、一个接口一分钟限制多少请求、一段时间内一个账号登录密码错误次数
  1. 登录密码错误次数限制
//登录入口类
//达到错误次数,返回过期时间提示
String count=valueOperations.get(key);
if(count!=null&&Long.valueOf(count).equals(failTimes)){
	Long expire=stringRedisTemplate.getExpire(key,TimeUnit.MINUTES);
    return "您输入密码错误次数过多,请{0}分钟后重试",expire;
}

//密码错误类
//错误一次+1
Long count=valueOperations.increment(key,1L);
//达到错误次数,从这一刻开始设置过期时间,并返回过期时间提醒
if(count.equals(failTimes)){
    stringRedisTemplate.expire(key,10,TimeUnit.MINUTES);
    return "您输入密码错误次数过多,请{0}分钟后重试",expire;
}

//密码正确类
//删除key,重新开始计数
stringRedisTemplate.delete(key);
  1. 序列号生成
    当项目迁移时数据库中数据有最大序列号,但是redis中没有,此时初始化为0是不对的;应该先判断redis中为空,再查询数据库中业务表使用的最大序列号,如果数据库中不为空,则利用缓存击穿的解决方式1来set最大序列号,然后再递增
//更新批次并返回
public String generateNewBatch(){
    HashOperations<String,String,String> hashOperations=stringRedisTemplate.opsForHash();
    ValueOperations<String,String> valueOperations=stringRedisTemplate.opsForValue();

    String key="project"+":";
    String batchKey=key+"batch";
    String batchOne="1";

    //批次
    long batch;
    //步长
    final long step=1L;
    Boolean exists=hashOperations.hasKey(batchKey,batchOne);
    //exists
    if(exists){
        //缓存+1
        batch=hashOperations.increment(batchKey,batchOne,step);
        //数据库+1
        save(new SyBatch().setSyId(batchOne).setBatch(batch));
    }else{
        String batchUpdateKey=key+"batch_update"+":"+batchOne;
        if(valueOperations.setIfAbsent(batchUpdateKey,batchUpdateKey,Duration.ofSeconds(30L))){
            //数据库中最大的批次
            Long maxBatch=syBatchMapper.queryMaxBatchBySyId(batchOne);
            //数据库中不存在
            if(maxBatch==null){
                batch=hashOperations.increment(batchKey,syIdStr,step);
                //数据库赋初值
                save(new SyBatch().setSyId(batchOne).setBatch(batch));
                //缓存赋初值
                hashOperations.put(batchKey,batchOne,String.valueOf(batch));
            }else{
                //数据库中存在则+1
                batch=maxBatch+step;
                //更新数据库
                save(new SyBatch().setSyId(syId).setBatch(batch)
                //更新缓存
                hashOperations.put(batchKey,batchOne,String.valueOf(batch));
            }
            //删除更新批次的缓存
            stringRedisTemplate.delete(batchUpdateKey);
        }else{//存在更新批次的缓存,说明批次正在更新,则等待
            Thread.sleep(30000);
            generateNewBatch();
        }
    }
    //2022123001
    return LocalDate.now().toString().replaceAll("-","")+String.format("%02d",batch);
}

4、排行榜

  • redis的zSet可以根据score顺序排列,新闻id作为value,点击数作为score,新闻点击一次,对应的新闻的score+1,最后根据reverseRange,获取指定区间的点击数最多的新闻

5、分布式锁

  • redis的setIfAbsent只有不存在才会set进去,服务器是集群的,定时任务可能在两台机器上都会运行,所以在定时任务中首先set一个lock,如果set成功则执行,set失败则该定时 任务正在执行,无需再执行;再结合过期时间
//设置一个关于该定时任务的key
if(redisTemplate.setIfAbsent(key,value)){ //true表示定时任务没有执行
    //执行定时任务
    //执行完成删除设置的key
}else{ //false表示定时任务正在执行
    //不执行定时任务
}

6、消息队列

  • redis的List操作的 左、右push、pop操作
  • 队列做触发式操作

7、点赞、签到、打卡

  • redis的Set,微博id作为key
  • 点赞的用户 = add这个集合
  • 取消点赞 = remove这个用户
  • 是否点赞 = 判断这个集合中是否存在该用户
  • 点赞的所有用户 = 获取这个集合中的所有用户点赞数 = 集的size

8、共同好友

  • 每个用户的好友add一个Set,计算交集
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kimi-001

只想在有限的时间分享更多的知识

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值