Redis SpringBoot项目学习

Redis 是一个高性能的key-value内存数据库。它支持常用的5种数据结构:String字符串、Hash哈希表、List列表、Set集合、Zset有序集合 等数据类型。
Redis它解决了2个问题:
第一个是:性能
通常数据库的读操作,一般都要几十毫秒,而redisd的读操作一般仅需不到1毫秒。通常只要把数据库的数据缓存进redis,就能得到几十倍甚至上百倍的性能提升。
第二个是:并发
在大并发的情况下,所有的请求直接访问数据库,数据库会出现连接异常,甚至卡死在数据库中。为了解决大并发卡死的问题,一般的做法是采用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问数据库。

1.String

Redis 中的字符串,直接就是按照字节数组(二进制数据)的方式存储的!不会做任何的编码转换,存的是啥,取出来就还是啥!不仅仅可以存储文本数据,还支持存储整数、文本、JSON、二进制数据等。
使用场景

  • 缓存: 存储临时数据,如用户会话、页面缓存。
  • 计数器: 用于统计访问量、点赞数等,通过原子操作增加或减少,

字符串类型是Redis最基础的数据类型,关于字符串需要特别注意:
首先Redis 中所有的键的类型都是字符串类型,而且其他几种数据结构也都是在字符串类似基础上构建的,例如列表和集合的元素类型是字符串类型,所以字符串类型能为其他4种数据结构的学习奠定基础。
其次,如下图所示,字符串类型的值实际可以是字符串,包含一般格式的字符串或者类似JSON、XML格式的字符串;数字,可以是整型或者浮点型;甚至是二进制流数据,例如图片、音频、视频等。不过一个字符串的最大值不能超过512 MB。
在这里插入图片描述

2.Hash

  • Redis的hash数据结构,其实就是string的升级版,它把string 数据结构的key value,中的value类型升级为hash(和java的hash一样的结构)
    Map<String, HashMap<String,String>> hash=new HashMap<String,HashMap<String,String>>();
  • 每个 hash的存储大小: 可以存储 2的(32 - 1)方的 键值对(40多亿)
    使用场景:
  • 商品详情:存储商品的各个属性,方便快速检索。

Redis存储java对象,一般是String 或 Hash 两种,那到底什么时候用String ? 什么时候用hash ?

String的存储通常用在频繁读操作,它的存储格式是json,即把java对象转换为json,然后存入redis.
Hash的存储场景应用在频繁写操作,即,当对象的某个属性频繁修改时,不适用string+json的数据结构,因为不灵活,每次修改都需要把整个对象转换为json存储。
如果采用hash,就可以针对某个属性单独修改,不用序列号去修改整个对象。例如,商品的库存、价格、关注数、评价数经常变动时,就使用存储hash结果

Redis实现双十一购物车

用户登录状态下添加商品到购物车
在这里插入图片描述
未登录用户状态下添加购物车
在这里插入图片描述
再次登录账号查看购物车(涉及未登录时的商品合并操作)
在这里插入图片描述

redis解决了分布式系统的session一致性问题
Session有什么作用?

Session 是客户端与服务器通讯会话跟踪技术,服务器与客户端保持整个通讯的会话基本信息。
客户端在第一次访问服务端的时候,服务端会响应一个sessionId并且将它存入到本地cookie中
在之后的访问会将cookie中的sessionId放入到请求头中去访问服务器,
如果通过这个sessionid没有找到对应的数据,那么服务器会创建一个新的sessionid并且响应给客户端。

分布式session的问题

在这里插入图片描述
在分布式系统中,通常会将 Session 存储在 Redis 中来实现 分布式 Session,这样就可以在多台服务器之间共享 Session 数据。实现分布式Session通常使用Redis的Hash结构:

  1. 在用户登录成功后,将 Session 数据存储在 Redis 中。
  2. 将 Redis 中的 Session 数据的 Key 设置为一个全局唯一的 ID,一般使用类似于“session:token”这样的格式,其中 token 是一个随机生成的字符串,用来标识这个 Session 数据。
  3. 在客户端返回响应的同时,将 Session ID(即 token)以 Cookie 的形式返回给客户端。客户端在后续的请求中都会携带这个 Cookie。
  4. 在后续的请求中,服务器会从客户端传递过来的 Cookie 中获取 Session ID,然后根据这个 ID 从 Redis 中获取对应的 Session 数据。如果 Redis 中没有找到对应的 Session 数据,那么就表示这个请求无法通过认证。
  5. 在用户退出登录或 Session 失效时,需要将 Redis 中的对应 Session 数据删除。

3.List

List类型是一个双端链表的结构,容量是2的32次方减1个元素,即40多亿个;
其主要功能有push、pop、获取元素等;一般应用在栈、队列、消息队列等场景。
使用场景:

  • 消息队列:用于简单任务调度、消息传递等场景,通过 LPUSH 和 RPOP 操作实现生产者消费者模式
  • 历史记录:存储用户操作的历史记录,便于快速访问
常用命令

以头插或尾插方式插入指定key队列中一个或多个元素
[LR]PUSH key value1 [value2 ...]
获取列表指定范围内的元素
LRANGE key start stop
查看列表所有元素
LRANGE key 0 -1
获取列表长度
LLEN key
通过索引获取列表中的元素
LINDEX key index

127.0.0.1:6379> lrange products 0 -1
1) "6"
2) "5"
3) "a"
4) "4"
5) "b"
6) "3"
7) "2"
8) "1"
127.0.0.1:6379> lindex products 2
"a"

通过索引设置列表元素的值
LSET key index value

127.0.0.1:6379> lrange products 0 -1
1) "6"
2) "5"
3) "a"
4) "4"
5) "b"
6) "3"
7) "2"
8) "1"
127.0.0.1:6379> lset products 2 A
OK
127.0.0.1:6379> lrange products 0 -1
1) "6"
2) "5"
3) "A"
4) "4"
5) "b"
6) "3"
7) "2"
8) "1"
Redis使用List实现商品分页展示

service

    public void runProductPage() {
   
   
        while (true){
   
   
            //模拟从数据库读取100件特价商品,用于加载到聚划算的页面中
            List<Product> list=this.products();
            //采用redis list数据结构的lpush来实现存储
            this.redisTemplate.delete(Constants.JHS_KEY);
            //lpush命令
            this.redisTemplate.opsForList().leftPushAll(Constants.JHS_KEY,list);
            try {
   
   
                //间隔一分钟 执行一遍
                Thread.sleep(1000*60);
            } catch (InterruptedException e) {
   
   
                e.printStackTrace();
            }
            log.info("runJhs定时刷新..............");
        }
    }

controller

    /**
     * 分页查询:在高并发的情况下,只能走redis查询,走db的话必定会把db打垮
     */
    @GetMapping(value = "/find")
    public List<Product> find(int page, int size) {
   
   
        List<Product> list=null;
        long start = (page - 1) * size;
        long end = start + size - 1;
        try {
   
   
            //采用redis list数据结构的lrange命令实现分页查询
            list = this.redisTemplate.opsForList().range(Constants.JHS_KEY, start, end);
            if (CollectionUtils.isEmpty(list)) {
   
   
                //TODO 走DB查询
            }
            log.info("查询结果:{}", list);
        } catch (Exception ex) {
   
   
            //这里的异常,一般是redis瘫痪 ,或 redis网络timeout
            log.error("exception:", ex);
            //TODO 走DB查询
        }
        return list;
    }
Redis使用List解决缓存击穿问题

在这里插入图片描述

采用主从轮询原理解决缓存击穿问题

在这里插入图片描述
在这里插入图片描述
service

public void runProductPageAB(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Jay_fearless

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值