Redis实战——缓存

article/2025/9/22 15:58:02

目录

1 前言

1.1什么是缓存?

1.2 缓存的作用及成本

 1.3 Redis缓存模型 

 2 给商户信息添加缓存

3 缓存更新策略 

3.1 更新策略介绍 

 3.2 主动更新策略

3.3 主动更新策略练习 

4 缓存穿透及其解决方案 

4.1 缓存穿透的概念

4.2 解决方案及实现

5 缓存雪崩的概念及其解决方案

6  缓存击穿及解决方案 

6.1什么是缓存击穿?

6.2 缓存击穿解决方法

6.2.1 互斥锁

6.2.2 逻辑过期


1 前言

1.1什么是缓存?

缓存就是数据交换的缓冲区(称作Cache [ kæʃ ] ),是存贮数据的临时地方,一般读写性能较高。

缓存有很多中实现场景:对于web开发,常见的有如下几种:

而我们的Redis缓存功能就是属于在应用层缓存 。

1.2 缓存的作用及成本

作用:毫无疑问,就是提高读写的效率,有效降低后端服务器的负载,有效降低响应时间。

成本:任何东西都有两面性,缓存在带来高效的读写效率的同时,也有着对应的从成本。

比如:数据一致性成本、代码维护成本、运维成本等。

 1.3 Redis缓存模型 

如下图

原本的模型应该是客户端发送请求给数据库,数据库返回数据给客户端,而Reids的缓存模型就是在原有的基础上,在中间加上一层Redis(经典的中间件思想~) 用户每次都会先去redis中查找数据,如果未命中才会去数据库中查找数据,并写入Reis当中,这么一来,用于下次需要相同的数据的时候,就可以在Reis当中进行获取,又因为Redis的高读写效率,实现了缓存的效果~

 2 给商户信息添加缓存

基于上述的Redis缓存模型,我们可以得出下面的缓存添加逻辑:

代码实现:(直接看Service层实现)

每次查询到商品用户信息后,添加缓存。

package com.hmdp.service.impl;import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.hmdp.dto.Result;
import com.hmdp.entity.Shop;
import com.hmdp.mapper.ShopMapper;
import com.hmdp.service.IShopService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;import java.util.concurrent.TimeUnit;import static com.hmdp.utils.RedisConstants.CACHE_SHOP_KEY;
import static com.hmdp.utils.RedisConstants.CACHE_SHOP_TTL;/*** <p>*  服务实现类* </p>** @author 虎哥* @since 2021-12-22*/
@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {@Resourceprivate StringRedisTemplate stringRedisTemplate;@Overridepublic Result queryShopById(Long id) {//1.去redis中查询商品是否存在String key = CACHE_SHOP_KEY+id;String shopJson = stringRedisTemplate.opsForValue().get(key);if (StrUtil.isNotBlank(shopJson)){//2.存在,直接返回给用户Shop shop = JSONUtil.toBean(shopJson, Shop.class);return Result.ok(shop);}//3.不存在,带着id去数据库查询是否存在商品Shop shop = getById(id);if (shop == null){//4.不存在,返回错误信息Result.fail("商品信息不存在!");}//5.存在,存入redisstringRedisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(shop));//6.返回商品信息return Result.ok(shop);}
}

3 缓存更新策略 

3.1 更新策略介绍 

使用Redis做缓存时,缓存还是要及时更新的,不然就会出现数据库和缓存数据不一致的情况,也是我们常说的Redis成本——数据一致性成本

缓存大致有以下三种更新策略:

1. 内存淘汰策略:这种策略没有维护成本,这是利用Redis的内存淘汰机制,当内存不足的时候自动淘汰,下次请求时再继续存入数据。

这种策略模型优点在于没有维护成本,但是内存不足这种无法预定的情况就导致了缓存中会有很多旧的数据,数据一致性差

2. 超时剔除:这种策略就是比较实用的,就是给缓存添加TTL存活时间,下次查询是更新缓存。

这种策略数据一致性一般,维护成本有但是较低,一般用于兜底方案~

3.主动更新策略:就是我们程序员手动的进行数据库和缓存之间的更新,但数据库更新时,缓存也进行更新。

这种策略数据一致性就是最高的(毕竟自己动手,丰衣足食),但同时维护成本也是最高的

 那么,又该如何选择缓存更新策略呢?

我的觉得应该是根据业务场景不同来选择不同的更新策略:

当数据一致性要求低时:l使用内存淘汰机制。例如店铺类型的查询缓存。

当有高一致性需求:使用主动更新并以超时剔除作为兜底方案。例如店铺详情查询的缓存 

 3.2 主动更新策略

上述提到的主动更新策略,无疑是维护成本最高的,但具体又有哪些维护方式呢?怎么去做主动更新维护呢?

如下图:主动更新主要分为下面三种:

 又因为后两种实现方式过于复杂,所以重点说第一种 。

第一种:Cache Aside Pattern,由缓存调用者进行操作,就是在我们数据库进行更新时,对缓存也进行更新。

这又引出了好几个问题了~

1. 缓存更新?是更新缓存还是直接删除缓存?

2. 如何保证数据库更新和缓存更新同时成功或失败?

3. 操作时应该先操作缓存还是先操作数据库?

第一个问题:

我想说,缓存更新如果是数据更新的话,每次更新数据库都要对缓存数据进行更新,有太多无效的读写操作,所以操作缓存时,选择删除缓存~

第二个问题:

要做到两个操作一致性,第一想到的就应该是事务。

解决方案:当我们是单体系统时,将缓存和数据库操作放在同一个事务里。

当我们是分布式系统时,利用TTC等分布式事务方案

最后一个问题:先操作数据库还是先操作缓存?

就只有下面两种情况:

1. 先删除缓存,再操作数据库 2. 先操作数据库,再删除缓存

我们可以两种情况都来看看~

第一种情况,先删除缓存的情况,我们想的正常的不会出现问题的操作流程(左边)操作会出现问题的流程 (右边)

补充一下:这边两个线程最初的数据库和缓存数据都假定为10~

 出现问题的情况为我们线程1先删除缓存,线程2未命中缓存,直接查到数据库中数据为10并写入缓存中,而线程1在线程2后写入缓存后,把数据库更新成了20,这样最后数据库数据为20,而缓存中的数据为10,这就导致数据不一致了。

2.先操作数据库的情况:

正确情况(左边)错误情况(右边),数据库和缓存最初数据也都还是10~

第二种先操作数据库的方式,它出现的错误情况主要是,线程1线程查询了缓存,未命中后去查询数据库的同时,线程2更新了数据库,并且删除了缓存,然后线程1才把数据库中查出来的10写入缓存,导致缓存为10,数据库为20。

终上所述,第一种失败的情况是比第二种失败的情况多的,因为第一种情况出现错误的时间是在删除缓存并更新数据库后,线程2有着充足的时间在这段时间内写入缓存,而对于第二种情况来说,出现问题发生在查完数据库到写入缓存这段时间内,这段时间几乎是毫秒级别的,线程2在这段时间内更新数据库并删除缓存,显然几率是很低的(除了高高高并发的状况下),所以我们选择先操作数据库在操作缓存~

总结:

缓存更新策略的最佳实践方案:

1.低一致性需求:使用Redis自带的内存淘汰机制

2.高一致性需求:主动更新,并以超时剔除作为兜底方案

主动更新时

进行读操作:

  • 缓存命中则直接返回
  • 缓存未命中则查询数据库,并写入缓存,设定超时时间

进行写操作:

  • 先写数据库,然后再删除缓存
  • 要确保数据库与缓存操作的原子性

3.3 主动更新策略练习 

修改商品缓存
1. 根据id查询店铺时,如果缓存未命中,则查询数据库,将数据库结果写入缓存,并设置超时时间
2. 根据id修改店铺时,先修改数据库,再删除缓存

实现代码如下(Service层实现):

package com.hmdp.service.impl;import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.hmdp.dto.Result;
import com.hmdp.entity.Shop;
import com.hmdp.mapper.ShopMapper;
import com.hmdp.service.IShopService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;import java.util.concurrent.TimeUnit;import static com.hmdp.utils.RedisConstants.CACHE_SHOP_KEY;
import static com.hmdp.utils.RedisConstants.CACHE_SHOP_TTL;/*** <p>*  服务实现类* </p>** @author 虎哥* @since 2021-12-22*/
@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {@Resourceprivate StringRedisTemplate stringRedisTemplate;@Overridepublic Result queryShopById(Long id) {//1.去redis中查询商品是否存在String key = CACHE_SHOP_KEY+id;String shopJson = stringRedisTemplate.opsForValue().get(key);if (StrUtil.isNotBlank(shopJson)){//2.存在,直接返回给用户Shop shop = JSONUtil.toBean(shopJson, Shop.class);return Result.ok(shop);}//3.不存在,带着id去数据库查询是否存在商品Shop shop = getById(id);if (shop == null){//4.不存在,返回错误信息Result.fail("商品信息不存在!");}//5.存在,存入redis(并设置超时时间)stringRedisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(shop),CACHE_SHOP_TTL, TimeUnit.MINUTES);//6.返回商品信息return Result.ok(shop);}@Override@Transactionalpublic Result updateShop(Shop shop) {//1.先更新数据库updateById(shop);//2.删除redis缓存String key = CACHE_SHOP_KEY+shop.getId();stringRedisTemplate.delete(key);return null;}
}

这样就能达到基本的主动缓存更新啦~

4 缓存穿透及其解决方案 

4.1 缓存穿透的概念

缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。

通俗的说,就是请求的数据在数据库和缓存中都没有,最后请求都到了数据库。这个时候,如果有一个恶意的程序员,通过某种方式不断请求一个不存在的数据,这样就会给数据库带来巨大的压力。(就怕用户懂代码)

4.2 解决方案及实现

常见的缓存穿透的解决方案有两种:

1.就是给redis缓存一个空对象并设置TTL存活时间

这种方式优点在于实现简单,维护方便,但也带来了额外的内存消耗和可能的短期的数据不一致

小知识:这里的数据不一致发生在用户刚从redis中拿到null值恰好数据插入了这个请求需要的值而导致的数据库Redis数据不一致。

2. 就是利用布隆过滤

通俗的说,就是中间件~

这种方式 优点在于内存消耗较小,没有多余的key,缺点就在于实现复杂,而且布隆过滤器有误判的可能...

代码实现:这里实现第一种 

就拿上述的写入商品信息为例:

我们只需要在数据库获取数据时,如果取到空值,不直接返回404,而是将空值也存入redis中,并且在判断缓存是否命中时,判断命中的值是不是我们传入的空值。如果是,直接结束,不是就返回商铺信息 

package com.hmdp.service.impl;import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.hmdp.dto.Result;
import com.hmdp.entity.Shop;
import com.hmdp.mapper.ShopMapper;
import com.hmdp.service.IShopService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;import java.util.concurrent.TimeUnit;import static com.hmdp.utils.RedisConstants.*;/*** <p>*  服务实现类* </p>** @author 虎哥* @since 2021-12-22*/
@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {@Resourceprivate StringRedisTemplate stringRedisTemplate;@Overridepublic Result queryShopById(Long id) {//1.去redis中查询商品是否存在String key = CACHE_SHOP_KEY+id;String shopJson = stringRedisTemplate.opsForValue().get(key);if (StrUtil.isNotBlank(shopJson)){//2.存在,直接返回给用户Shop shop = JSONUtil.toBean(shopJson, Shop.class);return Result.ok(shop);}//判断命中的是否为空字符串/*** (这里重点讲一下为什么是不等于:因为我们获取到的shopJson为null是,上面的isNotBlank方法会返回false,导致成为了不命中的效果)*/if (shopJson != null){return Result.fail("商品信息不存在!");}//3.不存在,带着id去数据库查询是否存在商品Shop shop = getById(id);if (shop == null){// 4.将空值存入redisstringRedisTemplate.opsForValue().set(key,"",CACHE_NULL_TTL,TimeUnit.MINUTES);//5.不存在,返回错误信息Result.fail("商品信息不存在!");}//6.存在,存入redis(并设置超时时间)stringRedisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(shop),CACHE_SHOP_TTL, TimeUnit.MINUTES);//7.返回商品信息return Result.ok(shop);}}

 总结:

缓存穿透产生的原因是什么?

用户请求的数据在缓存中和数据库中都不存在,不断发起这样的请求,给数据库带来巨大压力。

缓存穿透的解决方案有哪些?(3-6点为扩展~)

1.缓存null值

2.布隆过滤

3.增强id的复杂度,避免被猜测id规律

4.做好数据的基础格式校验

5.加强用户权限校验

6.做好热点参数的限流

5 缓存雪崩的概念及其解决方案

缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。

就是说,一群设置了有效期的key同时消失了,或者说redis罢工了,导致所有的或者说大量的请求会给数据库带来巨大压力叫做缓存雪崩~

解决方式也比较的简单~

1. 给不同的key添加随机的TTL存活时间(这种就是最简单的,设置存货时间随机各不相同)

2. 利用Redis集群(这种针对与Redis出现宕机的情况)

3. 给缓存业务添加降级限流策略(SpringCloud知识点)

4. 给业务添加多级缓存

6  缓存击穿及解决方案 

6.1什么是缓存击穿?

缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击。

大概的奔溃流程是这样子的:

第一个线程,查询redis发现未命中,然后去数据库查询并重建缓存,这个时候因为在缓存重建业务较为复杂的情况下,重建时间较久,又因为高并发的环境下,在线程1重建缓存的时间内,会有其他的大量的其他线程进来,发现查找缓存仍未命中,导致继续重建,如此死循环。

6.2 缓存击穿解决方法

常见的解决方案有两种:

6.2.1 互斥锁

互斥锁的解决方案如下:

就是当线程查询缓存未命中时,尝试去获取互斥锁,然后在重建缓存数据,在这段时间里,其他线程也会去尝试获取互斥锁,如果失败就休眠一段时间,并继续,不断重试,等到数据重建成功,其他线程就可以命中数据了。这样就不会导致缓存击穿。这个方案数据一致性是绝对的,但是相对来说会牺牲性能。

 实现方法:

1.获取互斥锁和释放锁的实现:

这里我们获取互斥锁可以使用redis中string类型中的setnx方法 ,因为setnx方法是在key不存在的情况下才可以创建成功的,所以我们重建缓存时,使用setnx来将锁的数据加入到redis中,并且通过判断这个锁的key是否存在,如果存在就是获取锁成功,失败就是获取失败,这样刚好可以实现互斥锁的效果。

而释放锁就更简单了,直接删除我们存入的锁的key来释放锁。

//获取锁public Boolean tryLock(String key){Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(key, "1", 10, TimeUnit.SECONDS);return BooleanUtil.isTrue(flag);}//释放锁方法public void unlock(String key){stringRedisTemplate.delete(key);}

2.实现代码:

具体操作流程如下图:

 

实现代码如下:

package com.hmdp.service.impl;import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.hmdp.dto.Result;
import com.hmdp.entity.Shop;
import com.hmdp.mapper.ShopMapper;
import com.hmdp.service.IShopService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.utils.RedisData;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;import java.time.LocalDateTime;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;import static com.hmdp.utils.RedisConstants.*;/*** <p>*  服务实现类* </p>** @author 虎哥* @since 2021-12-22*/
@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {@Resourceprivate StringRedisTemplate stringRedisTemplate;@Overridepublic Result queryShopById(Long id) {//互斥锁缓存击穿Shop shop = queryWithMutex(id);if (shop == null){Result.fail("商品信息不存在!");}//8.返回商品信息return Result.ok(shop);}// 缓存穿透解决——互斥锁public Shop queryWithMutex(Long id){//1.去redis中查询商品是否存在String key = CACHE_SHOP_KEY+id;String shopJson = stringRedisTemplate.opsForValue().get(key);if (StrUtil.isNotBlank(shopJson)){//2.存在,直接返回给用户Shop shop = JSONUtil.toBean(shopJson, Shop.class);return shop;}//判断命中的是否为空字符串if (shopJson != null){return null;}Shop shop = null;String lockKey = LOCK_SHOP_KEY+id;try {//3.缓存重建//3.1尝试获取锁Boolean isLock = tryLock(lockKey);//3.2判断获取锁是否成功,如果休眠重试if (!isLock){//休眠Thread.sleep(50);//重试用递归queryWithMutex(id);}//3.3如果成功,去数据库查找数据shop = getById(id);if (shop == null){// 4.将空值存入redisstringRedisTemplate.opsForValue().set(key,"",CACHE_NULL_TTL,TimeUnit.MINUTES);//5.不存在,返回错误信息Result.fail("商品信息不存在!");}//6.存在,存入redis(并设置超时时间)stringRedisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(shop),CACHE_SHOP_TTL, TimeUnit.MINUTES);} catch (InterruptedException e) {throw new RuntimeException(e);} finally {//7.释放锁unlock(lockKey);}//8.返回商品信息return shop;}//获取锁public Boolean tryLock(String key){Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(key, "1", 10, TimeUnit.SECONDS);return BooleanUtil.isTrue(flag);}//释放锁方法public void unlock(String key){stringRedisTemplate.delete(key);}}

 

6.2.2 逻辑过期

逻辑过期的处理方法主要为:

给redis缓存字段中添加一个过期时间,然后当线程查询数据库的时候,先判断是否已经过期,如果过期,就获取获取互斥锁,并开启一个子线程进行缓存重建任务,直到子线程完成任务后,释放锁。在这段时间内,其他线程获取互斥锁失败后,并不是继续等待重试,而是直接返回旧数据。这个方法虽然性能较好,但也牺牲了数据一致性。

 实现方法:

1.获取互斥锁和释放锁如上

2.给redis数据添加一个过期时间(创建一个RedisData类,并封装数据)

RedisData类:

package com.hmdp.utils;import lombok.Data;import java.time.LocalDateTime;@Data
public class RedisData {private LocalDateTime expireTime;private Object data;
}
//给商品信息添加一个过期时间字段,并存入redis当中public void saveShop2Redis(Long id,Long expireSeconds){Shop shop = getById(id);RedisData redisData = new RedisData();redisData.setData(shop);redisData.setExpireTime(LocalDateTime.now().plusSeconds(expireSeconds));stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY+id,JSONUtil.toJsonStr(redisData));}

然后就是业务实现了:

 

具体代码如下:

package com.hmdp.service.impl;import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.hmdp.dto.Result;
import com.hmdp.entity.Shop;
import com.hmdp.mapper.ShopMapper;
import com.hmdp.service.IShopService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.utils.RedisData;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;import java.time.LocalDateTime;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;import static com.hmdp.utils.RedisConstants.*;/*** <p>*  服务实现类* </p>** @author 虎哥* @since 2021-12-22*/
@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {@Resourceprivate StringRedisTemplate stringRedisTemplate;@Overridepublic Result queryShopById(Long id) {//逻辑过期解决缓存击穿问题
//        Shop shop = queryWithLogicalExpire(id);if (shop == null){Result.fail("商品信息不存在!");}//8.返回商品信息return Result.ok(shop);}private static final ExecutorService CACHE_REBUILD_EXECUTOR = Executors.newFixedThreadPool(10);public Shop queryWithLogicalExpire(Long id){//1.去redis中查询商品是否存在String key = CACHE_SHOP_KEY+id;String shopJson = stringRedisTemplate.opsForValue().get(key);//2.判断是否命中//3.未命中if (StrUtil.isBlank(shopJson)){return null;}//4.命中,先把redis中的数据反序列化成java对象RedisData redisData = JSONUtil.toBean(shopJson, RedisData.class);//4.1获取过期时间LocalDateTime expireTime = redisData.getExpireTime();//4.2获取商品对象JSONObject data = (JSONObject) redisData.getData();Shop shop = JSONUtil.toBean(data, Shop.class);//5.判断是否过期if (expireTime.isAfter(LocalDateTime.now())){//未过期,直接返回shopreturn shop;}//6.过期,重建缓存//6.1尝试获取锁,并判断String lockKey = LOCK_SHOP_KEY + id;Boolean isLock = tryLock(lockKey);if (isLock){//5.2 如果成功,开启一个独立的线程,重建缓存CACHE_REBUILD_EXECUTOR.submit(()->{try {//重建缓存this.saveShop2Redis(id,20L);} catch (Exception e) {throw new RuntimeException(e);} finally {//释放锁unlock(lockKey);}});}//6.2返回旧的商品信息return shop;}//获取锁public Boolean tryLock(String key){Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(key, "1", 10, TimeUnit.SECONDS);return BooleanUtil.isTrue(flag);}//释放锁方法public void unlock(String key){stringRedisTemplate.delete(key);}//给商品信息添加一个过期时间字段,并存入redis当中public void saveShop2Redis(Long id,Long expireSeconds){Shop shop = getById(id);RedisData redisData = new RedisData();redisData.setData(shop);redisData.setExpireTime(LocalDateTime.now().plusSeconds(expireSeconds));stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY+id,JSONUtil.toJsonStr(redisData));}}

 缓存知识结束。

 


http://chatgpt.dhexx.cn/article/QvjcYDyX.shtml

相关文章

SpringBoot整合Redis缓存

SpringBoot整合Redis缓存 一、缓存概念知识1、是什么缓存2、缓存的优缺点3、为什么使用缓存 二、Redis概念知识1、Redis简介2、为什么用Redis作为缓存3、Redis 支持的数据类型4、Redis缓存常见问题1. 缓存穿透2. 缓存击穿3. 缓存雪崩4. 缓存一致性 三、SpringBoot整合redis1、使…

云平台的层次架构

云计算平台 ​ 云计算是一种资源的服务模式&#xff0c;该模式可以实现随时随地、便捷按需地从可配置计算资源共享池中获取所需的资源(如网络、服务器、存储、应用及服务)&#xff0c;资源能够快速供应并释放&#xff0c;大大减少了资源管理工作开销。 ​ 经典云计算架构包括…

政务云平台服务

做政企项目交付&#xff0c;部署在政务云上的信息系统&#xff0c;经常会需要申请政务云资源&#xff0c;尤其是等保测评&#xff0c;还需要申请相关安全服务设施。 通过几个参考例子&#xff0c;简要说明政务云平台的自愿服务。 广州市信息化服务中心 广州市政府信息化云服…

SaaS的几种架构解析

转载&#xff1a;https://www.xugj520.cn/amp/SaaS_Architecture.html SAAS成熟度模型分级 LEVEL1 定制开发 软硬件都由SAAS服务商提供&#xff0c;软件的使用者只需要按时间、用户数、空间等逐步支付租赁使用费用即可 LEVEL2 可配置 通过不同的配置满足不同用户的需求&#…

SaaS云HIS系统源码功能介绍

SaaS云HIS首页功能&#xff1a;包括工作计划、预警、主功能菜单、医院机构公告。 一、工作计划 1.值班概况&#xff1a;值班日期、值班时间、值班科室&#xff08;内科、外科等&#xff09; 2.待处理患者&#xff1a;内科人数、外科人数等 病历统计&#xff1a;入院病历、出…

saas系统需要什么样的云服务器,SAAS系统和云服务器的区别

SAAS系统和云服务器的区别 内容精选 换一换 云耀云服务器默认设置的时区,是您制作镜像时选择的时区。如需修改,请参见本节内容,将其更改为所需的本地时间或网络中的其他时区。云耀云服务器登录成功后,如果发现云耀云服务器系统时间与本地时间不一致,建议更改时区,将云耀云…

虚拟化与云平台

虚拟化&#xff1a; 虚拟化技术就是指一台物理机上可以跑多台虚拟机&#xff0c;共享内存、CPU、IO等硬件资源&#xff0c;虚拟机之间在逻辑上是相互隔离的。 共享的物理机称为“宿主机”&#xff0c;虚拟机称为“客户机” 宿主机通过hypervisor将硬件资源虚拟化给客户机共享…

OneNET云平台

OneNET云平台 由中国移动打造的PaaS物联网开放平台。平台能够帮助开发者轻松实现设备接入与设备连接,快速完成产品开发部署,为智能硬件、智能家居产品提供完善的物联网解决方案。 OneNET致力于开发者的体验,逐步提升云服务体量,着手用户运营,深化运维管理和云端大数据分…

开源项目saas电商项目

1.线上电商私域电商一体化 数字化零售我们采用数字商城SaaS数字门店SaaS一体化结合赋能 数字门店SaaS&#xff0c;适用连锁门店&#xff0c;如杏花楼、廖记、奈雪的茶 数字商城SaaS&#xff0c;适用线上电商&#xff0c;对标《有赞》&#xff1b;如淘系商家 数字门店SaaS与数…

智能家居云平台设计

智能家居云平台设计 摘 要 智能家居是未来家居的发展方向&#xff0c;其利用先进的网络技术、计算机技术和无线通信技术等将家居中的各种电子电气设备连接起来&#xff0c;统一管理、远程监控和资源共享&#xff0c;实现了高效、便利的生活环境。近些年互联网的迅猛发展&…

云平台概念详解

1. 前言 随着云计算概念的不断落地和推广, 目前云平台已经得到了非常广泛的使用. 云平台帮助用户在: • 应用落地 • 服务落地 • 安全保障 • 性能 等方面获得比传统方式更高效, 更节省, 更稳定, 更方便的优势. 2. 云平台的概念 云平台也称云计算平台. 云计算…

云平台是什么、什么是云、云平台的分类、主流公有云平台有哪些、云的三种服务、PaaS、SaaS、IaaS

云平台的基础概念 1.1 前言 随着云计算概念的不断落地和推广, 目前云平台已经得到了非常广泛的使用. 云平台帮助用户在: 应用落地服务落地安全保障性能 等方面获得比传统方式更高效, 更节省, 更稳定, 更方便的优势. 1.2 云平台的概念 云平台也称云计算平台. 云计算, 顾名…

初代SAAS平台应用层架构设计

近期参与SAAS项目第一代应用设计&#xff0c;为满足整体灵活性&#xff0c;复用性和可定制化&#xff0c;得出如下应用层模型&#xff0c;希望能给大家相互参考学习&#xff0c;设计上有什么缺漏请多指教 核心思想 模块为最小化购买单位 例如商城模块 分销模块等多个模块组合…

SAP 云平台 (Cloud Platform) 架构概述

引言 在我们开始SAP云平台的架构之旅之前&#xff0c;让我们先看看SAP已经发布的一些其他云产品。这些云产品方案可以分为公有云和私有云两种。 SAP公有云解决方案见下图最右侧&#xff0c;比较著名的有SAP SuccessFactors和SAP Cloud for Customer(C4C)等&#xff0c;作为SAP软…

大型JAVA智慧校园云平台SaaS源码

▶ 让技术回归教育 智慧校园完整技术栈&#xff1a; 前后端分离 1、使用springboot框架Javavue2 2、数据库MySQL5.7 3、移动端小程序使用小程序原生语音开发 4、电子班牌固件安卓7.1&#xff1b;使用Java Android原生 5、elmentui &#xff0c;Quartz&#xff0c;jpa&#xff…

Saas免费开源充电桩平台

开源充电桩Saas系统&#xff08;v2.3.1&#xff09; 我的车&#xff0c;到底该选什么功率充电桩&#xff1a; 点我访问 体验地址&#xff0c;star star &#xff1a; 点我访问 日志记录 每天进步一点点&#xff0c;希望每天能更新一些进度。 系统更新日志 2022.10.4 重新整理PP…

多校园SaaS运营智慧校园云平台源码 智慧校园移动小程序源码

智慧校园管理平台源码 智慧校园云平台源码 智慧校园全套源码包含&#xff1a;电子班牌管理系统、成绩管理系统、考勤人脸刷卡管理系统、综合素养评价系统、请假管理系统、电子班牌发布系统、校务管理系统、小程序移动端、教师后台管理系统、SaaS运营云平台&#xff08;支持多学…

云平台的分类

要了解云平台之前&#xff0c;首先讲一下云计算 定义&#xff1a;云计算&#xff08;cloud computing&#xff09;是分布式计算的一种&#xff0c;指的是通过网络“云”将巨大的数据计算处理程序分解成无数个小程序&#xff0c;然后&#xff0c;通过多部服务器组成的系统进行处…

多租户saas云平台框架

今天谈下云平台下的多租户架构&#xff0c;不论是在公有云还是私有云平台&#xff0c;是设计一个面向最终组织或用户的 SaaS 应用还是面向业务系统的 PaaS 平台&#xff0c;多租户都是前期架构设计的一个关键内容&#xff0c;因此有必要对里面的一些核心要点进一步说明。 多租…

SAAS云平台搭建札记: (一)浅论SAAS多租户自助云服务平台的产品、服务和订单

最近在做一个多租户的云SAAS软件自助服务平台&#xff0c;途中遇到很多问题&#xff0c;我会将一些心得、体会逐渐分享出来&#xff0c;和大家一起探讨。这是本系列的第一篇文章。 大家知道&#xff0c;要做一个全自助服务的SAAS云平台是比较复杂的&#xff0c;稍微有些漏洞&am…