Blage's Coding Blage's Coding
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
  • Redis基础

  • 源码分析

  • 实战应用

  • 单机缓存

    • Caffeine
      • 集成SpringBoot
        • 方式一:将缓存作为bean对象
        • 方式二:SpringCache注解
      • 使用场景
        • 场景一、登录接口防刷
  • Redis
  • 单机缓存
phan
2023-11-14
目录

Caffeine

# Caffeine

作为单机服务的本地缓存,减少数据库的压力。它具有如下特征:

  • 缓存过期策略
  • 缓存淘汰策略(大小,lru)
  • 缓存剔除失效监听器

# 集成SpringBoot

主要介绍两种方式,个人比较喜欢第一种,配置操作灵活。

# 方式一:将缓存作为bean对象

安装pom相关依赖:

<dependency>
	<groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
</dependency>
1
2
3
4

添加配置类config/CaffineCacheConfig.java,直接构造缓存的Bean对象。

@Configuration
public class CaffineCacheConfig {
    @Bean
    public Cache<String,Integer> countCache(){
        return Caffeine.newBuilder().expireAfterWrite(100, TimeUnit.SECONDS)
                .initialCapacity(100)
                .maximumSize(1000)
                .build();
    }
}
1
2
3
4
5
6
7
8
9
10

在service当中,直接通过@Autowired注解拿到缓存对象。其中api如下:

  • getIfPresent(key):根据key获取缓存中的value值
  • invalidate(key):剔除缓存中key对应的条目
  • asMap:返回Map对象,用于遍历
@Service
public class UserService {
    @Autowired
    private Cache<String,Integer> countCache;
    
    public String getUserCount(String url) {
        Integer count = countCache.getIfPresent(url);
        count = count == null ? 1 : count + 1;
        countCache.put(url, count);
        String result = "";
        for (Map.Entry<String, Integer> entry : countCache.asMap().entrySet()) {
            result += entry.getKey() + ": " + String.valueOf(entry.getValue()) + "\n";
        }
        return result;
    }

    public void delKey(String url) {
        countCache.invalidate(url);
    }

    public void refreshAll() {
        countCache.invaludateAll();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 方式二:SpringCache注解

个人不是很喜欢~

安装pom依赖:

 <dependency>
 	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
	<groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
</dependency>
1
2
3
4
5
6
7
8

配置类中,需要注解CacheManage缓存管理器的Bean对象:

@Configuration
@EnableCaching
public class CacheConfig {
    @Bean("caffeineCacheManager")
    public CacheManager cacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager();
        cacheManager.setCaffeine(Caffeine.newBuilder()
                .expireAfterAccess(60, TimeUnit.SECONDS)
                .initialCapacity(100)
                .maximumSize(1000));
        return cacheManager;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

然后在service服务中,使用如下几种注解:

  • @Cacheable(key="#id"):先根据方法的形参作为key查找缓存,如果有直接返回。否则执行方法,并将方法的返回值存入cache
  • @CachePut(key = "#id"):向缓存插入数据
@Slf4j
@Service
@CacheConfig(cacheNames = "caffeineCacheManager")
public class UserInfoServiceImpl implements UserInfoService {
    @Override
    @CachePut(key = "#userInfo.id")
    public void addUserInfo(UserInfo userInfo) {
        userInfoMap.put(userInfo.getId(), userInfo);
    }

    @Override
    @Cacheable(key = "#id")
    public UserInfo getByName(Integer id) {
        return userInfoMap.get(id);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 使用场景

# 场景一、登录接口防刷

需求:登录失败累计三次,则需要在五分钟之后才允许重试,防止恶意登录攻击数据库。

核心:使用Caffeine的expireAfterAccess方法,设置最后一次访问后的过期时间5分钟。

只要用户访问次数超过了三次,则进行拦截。仅当用户不再恶意访问5min后,缓存才会自动清理key,重新计数,向数据库请求验证。这里key可以设置为用户的IP。

public class LoginService {
    private Cache<String, Integer> cache = Caffeine.newBuilder()
            .expireAfterAccess(5, TimeUnit.MINUTES)
            .maximumSize(1000).build();

    public boolean login() {
        String loginKey = requestUtils.getCurrentIp();
        if(!loginChect(loginKey)) return false;
        Integer count = cache.get(loginKey);
        cache.put(loginKey, count + 1);
        //查询数据库
        return true;
    }

    public boolean loginChect(String loginKey) {
        if (cache.getIfPresent(loginKey) > 3) {
            return false;
        }
        return true;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
编辑 (opens new window)
上次更新: 2023/12/15, 15:49:57
Redis面试

← Redis面试

Theme by Vdoing | Copyright © 2023-2024 blageCoder
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式