Redis项目中竟然有这么多种使用场景!!

news2024/11/15 18:05:00

下面蜗牛哥依次对Redis 15种业务场景举例说明和解释:

1. 排行榜和计数器

针对Redis作为排行榜和计数器的使用场景,下面是一个Java Spring Boot应用的案例,其中使用Redis来实现一个简单的文章点赞功能,并将点赞数用作排行榜的依据。

场景描述

假设我们正在开发一个博客平台,用户可以对文章进行点赞。

我们希望根据文章的点赞数来显示一个实时更新的热门文章排行榜。

创建Spring Boot项目

配置Redis连接

在src/main/resources/application.properties中配置Redis 服务器的连接信息:

spring.redis.host=localhost
spring.redis.port=6379

编写业务代码

  1. 定义文章实体类

public class Article {
    private String id;
    private String title;
    private int likeCount;
    // 省略构造函数、getter和setter方法
}
  1. 创建文章服务接口和实现类

@Service
public class ArticleService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    public void likeArticle(String articleId) {
        // 增加文章的点赞数
        redisTemplate.opsForValue().increment(articleId, 1);
    }

    public List<Article> getTopLikedArticles(int topN) {
        // 获取topN个点赞数最多的文章
        Set<String> articleIds = redisTemplate.keys("article:*:likeCount");
        List<Article> topArticles = new ArrayList<>();
        for (String id : articleIds) {
            int likeCount = (Integer) redisTemplate.opsForValue().get(id);
            Article article = new Article();
            article.setId(id.replace("article:", "").replace(":likeCount", ""));
            article.setTitle("文章标题待查询");
            article.setLikeCount(likeCount);
            topArticles.add(article);
        }
        // 根据点赞数排序
        topArticles.sort((a1, a2) -> a2.getLikeCount() - a1.getLikeCount());
        return topArticles.subList(0, topN);
    }
}
  1. 创建控制器

@RestController
@RequestMapping("/articles")
public class ArticleController {

    @Autowired
    private ArticleService articleService;

    @PostMapping("/{id}/like")
    public ResponseEntity<String> likeArticle(@PathVariable String id) {
        articleService.likeArticle(id);
        return ResponseEntity.ok("点赞成功");
    }

    @GetMapping("/top/{topN}")
    public ResponseEntity<List<Article>> getTopLikedArticles(@PathVariable int topN) {
        List<Article> topArticles = articleService.getTopLikedArticles(topN);
        return ResponseEntity.ok(topArticles);
    }
}

详细解释

图片

通过这种方式,我们可以利用Redis的原子操作和高性能特性来实现一个高效的点赞和排行榜功能。

每次用户点赞时,Redis都会原子性地更新点赞数,而获取排行榜时,我们可以快速地从Redis中检索和排序数据,从而提供实时的热门文章排行。

2. 实时分析

针对Redis作为实时分析使用场景,下面是一个Java Spring Boot应用的案例,其中使用Redis的Sorted Set来实现一个简单的用户在线时长统计和分析功能。

场景描述

假设我们正在开发一个在线教育平台,需要统计每个用户的在线时长,并根据这些数据生成实时的在线时长排行榜。

创建Spring Boot项目

配置Redis连接

在src/main/resources/application.properties中配置Redis服务器的连接信息:

spring.redis.host=localhost
spring.redis.port=6379

编写业务代码

  1. 用户在线时长服务接口和实现类

@Service
public class OnlineDurationService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    public void updateUserOnlineDuration(String userId, long duration) {
        // 使用Sorted Set存储用户ID和在线时长
        redisTemplate.opsForZSet().incrementScore("user:online:duration", userId, duration);
    }

    public Set<String> getTopUsersByOnlineDuration(int topN) {
        // 获取在线时长最长的前N个用户
        Set<String> topUsers = redisTemplate.opsForZSet().reverseRange("user:online:duration", 0, topN - 1);
        return topUsers;
    }
}
  1. 用户登录和登出逻辑

@Controller
public class UserController {

    @Autowired
    private OnlineDurationService onlineDurationService;

    @PostMapping("/user/{userId}/login")
    public ResponseEntity<String> userLogin(@PathVariable String userId) {
        // 用户登录逻辑,可以是任何触发登录的事件
        return ResponseEntity.ok("User " + userId + " logged in");
    }

    @PostMapping("/user/{userId}/logout")
    public ResponseEntity<String> userLogout(@PathVariable String userId) {
        // 用户登出时记录在线时长
        long duration = // 计算用户在线时长的逻辑
        onlineDurationService.updateUserOnlineDuration(userId, duration);
        return ResponseEntity.ok("User " + userId + " logged out");
    }
}
  1. 获取在线时长排行榜

@RestController
@RequestMapping("/users")
public class UserRankController {

    @Autowired
    private OnlineDurationService onlineDurationService;

    @GetMapping("/online-duration/top/{topN}")
    public ResponseEntity<Set<String>> getTopUsersByOnlineDuration(@PathVariable int topN) {
        Set<String> topUsers = onlineDurationService.getTopUsersByOnlineDuration(topN);
        return ResponseEntity.ok(topUsers);
    }
}

详细解释

图片

通过这种方式,我们可以利用Redis的Sorted Set来存储和排序用户的在线时长,实现一个高效的实时在线时长统计和分析功能。

每当用户登出时,系统都会更新用户的在线时长,并可以快速地根据在线时长对用户进行排名,从而提供一个动态的在线时长排行榜。这对于在线教育平台等需要监控用户活跃度的业务场景非常有用。

3. 分布式锁

针对Redis作为分布式锁的使用场景,下面是一个Java Spring Boot应用的案例,其中使用Redisson作为客户端来实现分布式锁。

场景描述

假设我们有一个高流量的电子商务网站,需要执行一些资源密集型的操作,比如生成日报表。为了防止多个实例同时执行这些操作,我们需要一个分布式锁来确保每次只有一个实例可以执行这些操作。

创建Spring Boot项目

配置Redisson连接

在src/main/resources/application.properties或application.yml中配置Redisson客户端连接到Redis服务器:

# application.properties
redisson.address=redis://localhost:6379

或者

# application.yml
redisson:
  address: "redis://localhost:6379"

编写业务代码

  1. 配置Redisson

创建一个配置类来配置Redisson客户端。

@Configuration
public class RedissonConfig {

    @Bean(destroyMethod = "shutdown")
    public RedissonClient redissonClient() {
        RedissonClientConfig config = new RedissonClientConfig();
        config.useSingleServer().setAddress(redisson.address);
        return Redisson.create(config);
    }

    @Value("${redisson.address}")
    private String redissonAddress;
}
  1. 使用分布式锁

创建一个服务类来执行需要分布式锁保护的资源密集型操作。

@Service
public class ReportService {

    @Autowired
    private RedissonClient redissonClient;

    public void generateDailyReport() {
        RLock lock = redissonClient.getLock("dailyReportLock");
        try {
            // 尝试获取锁,最多等待3秒,锁的自动过期时间设置为10秒
            if (lock.tryLock(3, 10, TimeUnit.SECONDS)) {
                // 执行生成日报表的操作
                System.out.println("Generating daily report...");
                // 模拟长时间运行的任务
                TimeUnit.SECONDS.sleep(5);
                System.out.println("Daily report generated.");
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            // 释放锁
            lock.unlock();
        }
    }
}
  1. 创建控制器

创建一个控制器来触发生成日报表的操作。

@RestController
@RequestMapping("/reports")
public class ReportController {

    @Autowired
    private ReportService reportService;

    @GetMapping("/daily")
    public ResponseEntity<String> generateDailyReport() {
        reportService.generateDailyReport();
        return ResponseEntity.ok("Daily report generation triggered.");
    }
}

详细解释

图片

通过这种方式,我们可以确保在分布式系统中,即使有多个实例运行,也只有一个实例可以执行生成日报表的操作,从而避免资源冲突和重复劳动。

Redisson客户端简化了Redis分布式锁的使用,使得在Spring Boot应用中实现分布式锁变得简单而高效。

4. 限流

针对Redis作为限流功能的使用场景,下面是一个Java Spring Boot应用的案例,其中使用Redis来实现API的限流。

场景描述

假设我们正在开发一个公共API服务,该服务需要对外部请求进行限流,以防止滥用和过载。我们希望对每个IP地址每分钟的请求次数进行限制。

创建Spring Boot项目

配置Redis连接

在src/main/resources/application.properties中配置Redis服务器的连接信息:

spring.redis.host=localhost
spring.redis.port=6379

编写业务代码

  1. 创建限流注解

定义一个自定义注解,用于标识需要限流的API。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RateLimit {
    int limit() default 10; // 默认每分钟请求次数限制
    long timeout() default 60; // 默认时间窗口为60秒
}
  1. 创建限流拦截器

实现一个拦截器来检查请求频率。

public class RateLimiterInterceptor implements HandlerInterceptor {

    private final RedisTemplate<String, Integer> redisTemplate;
    private final String rateLimitKeyPrefix = "rate_limit:";

    public RateLimiterInterceptor(RedisTemplate<String, Integer> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String ip = request.getRemoteAddr();
        String methodName = ((MethodSignature) (handler)).getMethod().getName();
        String rateLimitKey = rateLimitKeyPrefix + methodName + ":" + ip;

        int currentCount = redisTemplate.opsForValue().increment(rateLimitKey);
        if (currentCount > 1) {
            // 如果当前计数大于1,则说明请求已超过限制
            response.sendError(HttpServletResponse.SC_TOO_MANY_REQUESTS, "Too many requests, please try again later.");
            return false;
        }

        // 设置过期时间
        redisTemplate.expire(rateLimitKey, RateLimit.class.cast(((MethodSignature) handler).getMethod().getAnnotation(RateLimit.class)).timeout(), TimeUnit.SECONDS);
        return true;
    }
}
  1. 配置拦截器

配置拦截器以应用于所有控制器。

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private RateLimiterInterceptor rateLimiterInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(rateLimiterInterceptor);
    }
}
  1. 应用限流注解

在需要限流的API上应用自定义的RateLimit注解。

@RestController
public class ApiController {

    @RateLimit(limit = 5, timeout = 60) // 每分钟最多5个请求
    @GetMapping("/api/resource")
    public ResponseEntity<String> getLimitedResource() {
        return ResponseEntity.ok("Access to limited resource");
    }
}

详细解释

图片

通过这种方式,我们可以利用Redis的原子递增操作和键过期特性来实现API的限流。

每次请求都会检查当前IP的请求计数,如果超过限制,则返回429错误码(Too Many Requests)。

这有助于保护API免受滥用,并确保服务的稳定性和可用性。

5. 全页缓存

针对Redis作为全页缓存的使用场景,下面是一个Java Spring Boot应用的案例,其中使用Redis来缓存整个页面的HTML内容。

场景描述

假设我们正在开发一个新闻网站,该网站的首页包含多个新闻文章的摘要信息。由于首页访问频率很高,我们希望将整个首页的内容缓存起来,以减少数据库的查询次数和页面渲染时间。

创建Spring Boot项目

配置Redis连接

在src/main/resources/application.properties中配置Redis服务器的连接信息:

spring.redis.host=localhost
spring.redis.port=6379

编写业务代码

  1. 创建新闻文章服务

@Service
public class NewsService {

    // 假设有一个方法来获取新闻列表
    public List<Article> getNewsList() {
        // 这里是获取新闻列表的逻辑
        return Collections.emptyList();
    }
}
  1. 配置Redis缓存

创建一个配置类来设置Spring Cache和Redis缓存。

@Configuration
@EnableCaching
public class CacheConfig {

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        RedisCacheManager cacheManager = new RedisCacheManager(connectionFactory);
        // 设置缓存过期时间(例如5分钟)
        cacheManager.setDefaultExpiration(300);
        return cacheManager;
    }
}
  1. 创建控制器和视图

创建一个控制器来返回首页,并使用Redis缓存整个页面。

@Controller
public class NewsController {

    @Autowired
    private NewsService newsService;

    @Autowired
    private CacheManager cacheManager;

    @GetMapping("/")
    @Cacheable(value = "homePage", condition = "#root.caches[0].name == 'homePage'")
    public String homePage(Model model) {
        // 尝试从缓存中获取页面
        model.addAttribute("newsList", newsService.getNewsList());
        return "home";
    }
}
  1. 创建Thymeleaf模板

创建一个Thymeleaf模板home.html来渲染首页。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>首页</title>
</head>
<body>
    <h1>新闻首页</h1>
    <div th:each="article : ${newsList}">
        <h2 th:text="${article.title}"></h2>
        <p th:text="${article.summary}"></p>
    </div>
</body>
</html>

详细解释

图片

通过这种方式,我们可以利用Redis来缓存整个页面的内容。

首页的访问非常频繁,通过缓存可以显著减少数据库的查询次数和页面渲染时间,提高网站的响应速度和性能。

此外,Spring的缓存抽象和Thymeleaf模板使得实现全页缓存变得简单而高效。

6. 社交功能

针对Redis作为社交功能存储的使用场景,下面是一个Java Spring Boot应用的案例,其中使用Redis来存储用户的社交关系信息,如好友列表和用户状态更新。

场景描述

假设我们正在开发一个社交网络平台,用户可以添加好友,并且可以发布状态更新。我们需要存储每个用户的好友列表以及状态更新的时间线。

创建Spring Boot项目

配置Redis连接

在src/main/resources/application.properties中配置Redis服务器的连接信息:

spring.redis.host=localhost
spring.redis.port=6379

编写业务代码

  1. 定义用户和状态更新实体类

public class User {
    private String id;
    private String name;
    // 省略构造函数、getter和setter方法
}

public class StatusUpdate {
    private String userId;
    private String content;
    private Instant timestamp;
    // 省略构造函数、getter和setter方法
}
  1. 创建社交服务

@Service
public class SocialService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    public void addFriend(String userOneId, String userTwoId) {
        // 使用集合存储用户的好友列表
        redisTemplate.opsForSet().add("friends:" + userOneId, userTwoId);
        redisTemplate.opsForSet().add("friends:" + userTwoId, userOneId);
    }

    public Set<String> getFriends(String userId) {
        // 获取用户的好友列表
        return redisTemplate.opsForSet().members("friends:" + userId);
    }

    public void postStatusUpdate(String userId, String content) {
        // 使用列表存储用户的状态更新时间线
        StatusUpdate statusUpdate = new StatusUpdate(userId, content, Instant.now());
        redisTemplate.opsForList().rightPush("timeline:" + userId, statusUpdate);
    }

    public List<StatusUpdate> getStatusUpdates(String userId) {
        // 获取用户的状态更新时间线
        return redisTemplate.opsForList().range("timeline:" + userId, 0, -1);
    }
}
  1. 创建控制器

@RestController
@RequestMapping("/social")
public class SocialController {

    @Autowired
    private SocialService socialService;

    @PostMapping("/addFriend")
    public ResponseEntity<String> addFriend(@RequestParam String userOneId, @RequestParam String userTwoId) {
        socialService.addFriend(userOneId, userTwoId);
        return ResponseEntity.ok("Friends added successfully");
    }

    @GetMapping("/friends/{userId}")
    public ResponseEntity<Set<String>> getFriends(@PathVariable String userId) {
        Set<String> friends = socialService.getFriends(userId);
        return ResponseEntity.ok(friends);
    }

    @PostMapping("/status")
    public ResponseEntity<String> postStatusUpdate(@RequestParam String userId, @RequestParam String content) {
        socialService.postStatusUpdate(userId, content);
        return ResponseEntity.ok("Status updated successfully");
    }

    @GetMapping("/timeline/{userId}")
    public ResponseEntity<List<StatusUpdate>> getStatusUpdates(@PathVariable String userId) {
        List<StatusUpdate> updates = socialService.getStatusUpdates(userId);
        return ResponseEntity.ok(updates);
    }
}

详细解释

图片

通过这种方式,我们可以利用Redis的高性能和数据结构特性来实现社交网络平台中的社交功能。

Redis的Set和List数据结构非常适合存储和管理好友关系和状态更新时间线,能够提供快速的读写性能,满足社交网络平台的需求。

7. 实时推荐系统

针对Redis作为实时推荐系统存储的使用场景,下面是一个Java Spring Boot应用的案例,其中使用Redis来存储用户行为数据和偏好,以及提供一个简单的推荐功能。

场景描述

假设我们正在开发一个电子商务平台,我们希望根据用户的浏览和购买历史来推荐商品。我们将使用Redis来存储用户的这些行为数据,并根据这些数据生成推荐。

创建Spring Boot项目

配置Redis连接

在src/main/resources/application.properties中配置Redis服务器的连接信息:

spring.redis.host=localhost
spring.redis.port=6379

编写业务代码

  1. 创建商品和用户实体类

public class Product {
    private String id;
    private String name;
    // 省略构造函数、getter和setter方法
}

public class User {
    private String id;
    private String username;
    // 省略构造函数、getter和setter方法
}
  1. 创建推荐服务

@Service
public class RecommendationService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    public void recordView(String userId, String productId) {
        // 记录用户查看的商品
        redisTemplate.opsForList().leftPush("user:" + userId + ":views", productId);
    }

    public List<String> recommendProducts(String userId) {
        // 简单推荐算法:返回用户查看次数最多的商品
        Set<String> viewedProducts = redisTemplate.opsForSet().members("user:" + userId + ":views");
        Map<String, Long> productViewCounts = new HashMap<>();
        viewedProducts.forEach(productId -> {
            long count = redisTemplate.opsForValue().decrement("user:" + userId + ":views:" + productId);
            productViewCounts.put(productId, count);
        });

        return productViewCounts.entrySet().stream()
                .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
    }
}
  1. 创建控制器

@RestController
@RequestMapping("/recommendations")
public class RecommendationController {

    @Autowired
    private RecommendationService recommendationService;

    @PostMapping("/view")
    public ResponseEntity<String> recordProductView(@RequestParam String userId, @RequestParam String productId) {
        recommendationService.recordView(userId, productId);
        return ResponseEntity.ok("View recorded");
    }

    @GetMapping("/products")
    public ResponseEntity<List<String>> getRecommendations(@RequestParam String userId) {
        List<String> recommendedProducts = recommendationService.recommendProducts(userId);
        return ResponseEntity.ok(recommendedProducts);
    }
}

详细解释

图片

通过这种方式,我们可以利用Redis的高性能和简单的数据结构来快速记录用户行为并生成推荐。

虽然这里的推荐算法非常简单,但它展示了如何使用Redis来实现实时推荐系统的基础功能。

在实际应用中,推荐算法可能会更复杂,涉及机器学习模型和更丰富的用户行为数据。

8. 地理位置信息

针对Redis作为地理位置信息存储的使用场景,下面是一个Java Spring Boot应用的案例,其中使用Redis的Geospatial索引来实现基于地理位置的推荐功能。

场景描述

假设我们正在开发一款基于位置的社交应用,用户可以查看附近的其他用户或地点。我们需要存储用户的地理位置,并能够查询给定位置附近的用户。

创建Spring Boot项目

配置Redis连接

在src/main/resources/application.properties中配置Redis服务器的连接信息:

spring.redis.host=localhost
spring.redis.port=6379

编写业务代码

  1. 创建用户实体类

public class User {
    private String id;
    private String name;
    private double longitude;
    private double latitude;
    // 省略构造函数、getter和setter方法
}
  1. 创建地理位置服务

@Service
public class GeoLocationService {

    @Autowired
    private RedisTemplate<String, User> redisTemplate;

    public void addLocation(String userId, double longitude, double latitude) {
        User user = new User(userId, "username", longitude, latitude);
        // 使用Geospatial索引存储用户位置
        redisTemplate.opsForGeo().add("userLocations", new GeoLocation(user.getLongitude(), user.getLatitude()), userId);
    }

    public List<User> getUsersNearby(double longitude, double latitude, double radius) {
        // 查询给定位置附近的用户
        List<GeoWithin> nearbyUsersGeo = redisTemplate.opsForGeo().radius("userLocations",
                new Circle(new GeoCoordinate(latitude, longitude), radius),
                RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs());
        
        List<User> nearbyUsers = new ArrayList<>();
        for (GeoWithin geoWithin : nearbyUsersGeo) {
            nearbyUsers.add(redisTemplate.opsForValue().get(geoWithin.getMember()));
        }
        return nearbyUsers;
    }
}
  1. 创建控制器

@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private GeoLocationService geoLocationService;

    @PostMapping("/addLocation")
    public ResponseEntity<String> addLocation(@RequestParam String userId,
                                               @RequestParam double longitude,
                                               @RequestParam double latitude) {
        geoLocationService.addLocation(userId, longitude, latitude);
        return ResponseEntity.ok("User location added");
    }

    @GetMapping("/nearby")
    public ResponseEntity<List<User>> getUsersNearby(@RequestParam double longitude,
                                                      @RequestParam double latitude,
                                                      @RequestParam double radius) {
        List<User> nearbyUsers = geoLocationService.getUsersNearby(longitude, latitude, radius);
        return ResponseEntity.ok(nearbyUsers);
    }
}

详细解释

图片

通过这种方式,我们可以利用Redis的Geospatial索引来存储和查询地理位置信息。这对于需要基于地理位置提供服务的应用非常有用,如社交网络、共享出行、本地服务推荐等。

Redis的Geospatial索引提供了高效的邻近查询功能,可以快速找到指定范围内的用户或其他地理位置相关的实体。

9. 时间序列数据

针对Redis作为时间序列数据存储的使用场景,下面是一个Java Spring Boot应用的案例,其中使用Redis来存储和查询时间序列数据。

场景描述

假设我们正在开发一个监控系统,需要记录服务器的CPU使用率随时间变化的数据。我们将使用Redis的时间序列数据结构来存储这些监控数据,并能够查询任意时间范围内的CPU使用率。

创建Spring Boot项目

配置Redis连接

在src/main/resources/application.properties中配置Redis服务器的连接信息:

spring.redis.host=localhost
spring.redis.port=6379

编写业务代码

  1. 创建监控数据实体类

public class CpuUsageData {
    private Instant timestamp;
    private double cpuUsage;

    // 省略构造函数、getter和 setter 方法
}
  1. 创建监控服务

@Service
public class MonitoringService {

    @Autowired
    private LettuceConnectionFactory connectionFactory;

    public void logCpuUsage(String serverId, double cpuUsage) {
        // 记录CPU使用率数据
        CpuUsageData data = new CpuUsageData(Instant.now(), cpuUsage);
        // 使用Lettuce客户端的命令执行器来与RedisTimeSeries模块交互
        StatefulRedisConnection<String, CpuUsageData> connection = connectionFactory.connect();
        try {
            RedisTimeSeriesCommands<String, CpuUsageData> ts = connection.sync();
            ts.add(serverId, data.getTimestamp().toEpochMilli() / 1000, data);
        } finally {
            connection.close();
        }
    }

    public List<CpuUsageData> getCpuUsageHistory(String serverId, Instant start, Instant end) {
        // 查询指定时间范围内的CPU使用率历史数据
        List<CpuUsageData> history = new ArrayList<>();
        StatefulRedisConnection<String, CpuUsageData> connection = connectionFactory.connect();
        try {
            RedisTimeSeriesCommands<String, CpuUsageData> ts = connection.sync();
            Range range = Range.create(start.toEpochMilli() / 1000, end.toEpochMilli() / 1000);
            Cursor<CpuUsageData> cursor = ts.rangeRead(serverId, range);
            while (cursor.hasNext()) {
                history.add(cursor.next().getValue());
            }
        } finally {
            connection.close();
        }
        return history;
    }
}
  1. 创建控制器

@RestController
@RequestMapping("/monitoring")
public class MonitoringController {

    @Autowired
    private MonitoringService monitoringService;

    @PostMapping("/logCpuUsage")
    public ResponseEntity<String> logCpuUsage(@RequestParam String serverId, @RequestParam double cpuUsage) {
        monitoringService.logCpuUsage(serverId, cpuUsage);
        return ResponseEntity.ok("CPU usage logged");
    }

    @GetMapping("/cpuUsageHistory")
    public ResponseEntity<List<CpuUsageData>> getCpuUsageHistory(@RequestParam String serverId,
                                                                 @RequestParam Instant start,
                                                                 @RequestParam Instant end) {
        List<CpuUsageData> history = monitoringService.getCpuUsageHistory(serverId, start, end);
        return ResponseEntity.ok(history);
    }
}

详细解释

图片

通过这种方式,我们可以利用Redis的RedisTimeSeries模块来存储和查询时间序列数据。这对于需要监控和分析随时间变化的数据的应用非常有用,如服务器监控、网站访问量分析等。

RedisTimeSeries提供了高效的时间序列数据存储和查询功能,可以快速插入和检索大量时间戳数据。

10. 任务调度

针对Redis作为任务调度的使用场景,下面是一个Java Spring Boot应用的案例,其中使用Redis的延迟队列特性来实现任务调度。

场景描述

假设我们正在开发一个定时任务管理系统,需要安排一些任务在将来的某个时间点执行。我们将使用Redis的schedule命令来安排任务的执行。

配置Redis连接

在src/main/resources/application.properties中配置Redis服务器的连接信息:

spring.redis.host=localhost
spring.redis.port=6379

编写业务代码

  1. 创建任务调度服务

@Service
public class TaskSchedulingService {

    @Autowired
    private RedisTemplate<String, Runnable> redisTemplate;

    public void scheduleTask(Runnable task, long delay, TimeUnit timeUnit) {
        // 将任务和延迟时间存储到Redis中
        redisTemplate.opsForValue().set(
            "task:" + task.hashCode(), 
            task, 
            timeUnit.toSeconds(delay), 
            timeUnit
        );
        // 使用schedule命令安排任务在未来执行
        String scheduleCommand = String.format(
            "SCHEDULE %d %s", 
            System.currentTimeMillis() + timeUnit.toMillis(delay), 
            "task:" + task.hashCode()
        );
        redisTemplate.execute((RedisConnection connection) -> {
            connection.schedule(scheduleCommand);
            return null;
        });
    }
}
  1. 创建具体的任务

public class SampleTask implements Runnable {
    @Override
    public void run() {
        System.out.println("Task is running: " + LocalDateTime.now());
        // 执行任务逻辑
    }
}
  1. 创建控制器

@RestController
@RequestMapping("/tasks")
public class TaskController {

    @Autowired
    private TaskSchedulingService taskSchedulingService;

    @PostMapping("/schedule")
    public ResponseEntity<String> scheduleTask(@RequestParam long delay, @RequestParam TimeUnit timeUnit) {
        taskSchedulingService.scheduleTask(new SampleTask(), delay, timeUnit);
        return ResponseEntity.ok("Task scheduled for execution at " + LocalDateTime.now().plusNanos(timeUnit.toNanos(delay)));
    }
}

详细解释

图片

通过这种方式,我们可以利用Redis的schedule命令来安排任务的执行。这对于需要执行定时任务的应用非常有用,如定时数据备份、定时发送通知等。

通过Redis的延迟队列特性,我们可以简化任务调度的复杂性,并且能够灵活地安排任务在未来的任意时间点执行。

11. 数据共享

针对Redis作为数据共享的使用场景,下面是一个Java Spring Boot应用的案例,其中使用Redis来实现微服务架构中的服务间数据共享。

场景描述

假设我们有一个电商平台,它由多个微服务组成,比如用户服务、产品服务和订单服务。这些服务需要共享购物车数据,以确保用户在平台上的购物体验是连贯的。我们将使用Redis来存储和共享购物车数据。

创建Spring Boot项目

配置Redis连接

在src/main/resources/application.properties中配置Redis服务器的连接信息:

spring.redis.host=localhost
spring.redis.port=6379

编写业务代码

  1. 创建购物车项实体类

public class CartItem {
    private String productId;
    private int quantity;
    // 省略构造函数、getter和setter方法
}
  1. 创建购物车服务

@Service
public class CartService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    public void addToCart(String cartId, String productId, int quantity) {
        // 将购物车项存储到Redis的Hash结构中
        redisTemplate.opsForHash().put("cart:" + cartId, productId, quantity);
    }

    public Map<String, Integer> getCart(String cartId) {
        // 从Redis获取购物车内容
        return redisTemplate.opsForHash().entries("cart:" + cartId);
    }
}
  1. 创建控制器

@RestController
@RequestMapping("/cart")
public class CartController {

    @Autowired
    private CartService cartService;

    @PostMapping("/{cartId}/items")
    public ResponseEntity<String> addToCart(@PathVariable String cartId,
                                             @RequestParam String productId,
                                             @RequestParam int quantity) {
        cartService.addToCart(cartId, productId, quantity);
        return ResponseEntity.ok("Item added to cart");
    }

    @GetMapping("/{cartId}")
    public ResponseEntity<Map<String, Integer>> getCart(@PathVariable String cartId) {
        Map<String, Integer> cart = cartService.getCart(cartId);
        return ResponseEntity.ok(cart);
    }
}

详细解释

图片

通过这种方式,我们可以利用Redis的高性能和数据共享能力来实现微服务架构中的服务间数据共享。

购物车数据被存储在Redis中,可以被不同的微服务实例访问和修改,确保了数据的一致性和实时性。

这对于需要高度协同工作的分布式系统非常有用,如电商平台、在线协作工具等。

12. 持久化

针对Redis作为任务调度使用场景,下面是一个Java Spring Boot应用的案例,其中使用Spring的@Scheduled注解与Redisson结合来实现任务调度。

场景描述

假设我们有一个自动化的营销平台,需要定期(例如每天凌晨1点)执行一些任务,比如发送时事通讯邮件给订阅用户。我们将使用Spring的定时任务功能结合Redisson来确保分布式环境下任务的准时和准确执行。

创建Spring Boot项目

配置Redis连接

在src/main/resources/application.properties中配置Redis服务器的连接信息:

spring.redis.host=localhost
spring.redis.port=6379

编写业务代码

  1. 创建任务执行服务

@Service
public class ScheduledTaskService {

    public void executeTask() {
        // 执行任务的逻辑,例如发送邮件
        System.out.println("Executing scheduled task: " + LocalDateTime.now());
    }
}
  1. 配置Redisson

创建一个配置类来配置Redisson客户端。

@Configuration
public class RedissonConfig {

    @Bean(destroyMethod = "shutdown")
    public RedissonClient redissonClient() {
        RedissonClientConfig config = new RedissonClientConfig();
        config.useSingleServer().setAddress("redis://" + spring.redis.host + ":" + spring.redis.port);
        return Redisson.create(config);
    }

    @Value("${spring.redis.host}")
    private String redisHost;

    @Value("${spring.redis.port}")
    private int redisPort;
}
  1. 创建定时任务配置

使用Redisson的RedissonScheduledExecutorService来创建一个分布式的调度器。

@Configuration
public class ScheduledConfig {

    @Bean
    public RedissonScheduledExecutorService redissonScheduledExecutorService(RedissonClient redissonClient) {
        return redissonClient.getExecutorService("myScheduler");
    }
}
  1. 创建定时任务

使用Spring的@Scheduled注解和Redisson的调度器来执行定时任务。

@Component
public class ScheduledTasks {

    @Autowired
    private ScheduledTaskService taskService;

    @Autowired
    private RedissonScheduledExecutorService scheduler;

    @Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行
    public void scheduledTask() {
        scheduler.schedule(() -> taskService.executeTask(), 0, TimeUnit.SECONDS);
    }
}

详细解释

图片

通过这种方式,我们可以利用Spring的定时任务功能和Redisson的分布式调度器来实现任务调度。

这确保了即使在分布式系统中,任务也能准时和准确地执行,避免了任务执行的冲突和重复。

这对于需要定时执行的任务,如发送时事通讯、数据备份、报告生成等场景非常有用。

最后说一句(求关注!别白嫖!)

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。

关注公众号:woniuxgg,在公众号中回复:笔记  就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1813038.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Django UpdateView视图

UpdateView是Django中的一个通用视图&#xff0c;用于处理对象的更新操作。它允许用户更新一个已经存在的对象。UpdateView通常与一个模型表单一起使用&#xff0c;这样用户就可以看到当前对象的值&#xff0c;并可以修改它们。 1&#xff0c;添加视图 Test/app3/views.py fr…

什么是覆盖索引 ?

走当前索引就足够&#xff0c;而无需回表就能找到所有数据&#xff0c;就叫覆盖索引。 比如 key1 上有索引。&#xff08;它是一个普通的二级索引&#xff09;。 那么select key1 from s1 where key1 a 这种就叫覆盖索引。 表现就是explain时&#xff0c; Extra 那里显示 …

鸿蒙开发文件管理:【@ohos.fileio (文件管理)】

文件管理 该模块提供文件存储管理能力&#xff0c;包括文件基本管理、文件目录管理、文件信息统计、文件流式读写等常用功能。 说明&#xff1a; 本模块首批接口从API version 6开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 impor…

AI创意广告案例分析️可口可乐、麦当劳、伊利、钟薛高等一线品牌各显神通

AI 相关的教学我们最近做了不少分享&#xff0c;本期计育韬老师则希望和广告人们谈一谈具体的落地案例应用及其内在创意方法论。结合在 Midjourney 频道 LV.14 的部分创作经验&#xff0c;相信能为广大品牌方带来 AI 广告创作的启迪。 担心版权争议&#xff1f; 那就主打 UG…

分离轴定理:凸多边形相交检测算法

分离轴定理&#xff08;Seperating Axis Theorem&#xff09;是一种确定两个凸多边形是否相交的方法。该算法还可用于查找最小穿透向量&#xff0c;这对于物理模拟和许多其他应用非常有用。SAT 是一种快速通用算法&#xff0c;可以消除对每个形状类型对进行碰撞检测代码的需求&…

在Vue2和Vue3中ECharts如何使用,详细步骤,ref,$ref。echarts官网。

不管是在vue2中还是在vue3中其实本质上的原理和步骤都是一样的&#xff0c;只是语法可能有所不同。 为了方便大家看起乱&#xff0c;vue2和vue3我分开写。 echarts官网&#xff1a; https://echarts.apache.org/zh/index.html Vue2篇&#xff1a; 1.导入echarts包&#xf…

LaDM3IL:多实例学习用于免疫库分类

一个人的免疫组库由某一时间点的大量适应性免疫受体组成&#xff0c;代表了该个体的适应性免疫状态。免疫组库分类和相关受体识别有可能为新型疫苗的开发做出贡献。大量的实例对免疫组库分类提出了挑战&#xff0c;这可以表述为大规模多实例学习 (MMIL&#xff0c;Massive Mult…

AI实时免费在线图片工具4:WordArt艺术字生成;IC-Light打光模型;screenshot to code图像直接生成网页

1、艺术字生成WordArt https://modelscope.cn/studios/WordArt/WordArt/summary?reftop.aibase.com 2、打光模型IC-Light https://huggingface.co/spaces/lllyasviel/IC-Light Screenshot to Code图像直接生成网页 https://huggingface.co/spaces/HuggingFaceM4/screen…

Ubuntu,Linux服务器安装Mellanox MCX653105A IB网卡HCA卡驱动

驱动下载地址 https://network.nvidia.com/products/infiniband-drivers/linux/mlnx_ofed/ 选择对应操作系统 进入目录运行 安装成功显示 如果中途报错&#xff0c;需要核对下载的版本&#xff0c;并且把原来安装的卸载

钡铼BL102优化生产流程PLC-MQTT网关快速转换

在智能制造和工业4.0的推动下&#xff0c;优化生产流程、提升自动化水平已成为现代制造业的核心诉求。作为这一进程的关键环节&#xff0c;将传统的PLC控制系统与先进的物联网技术相结合&#xff0c;实现数据的高效采集与远程管理变得尤为重要。钡铼BL102作为一款专为优化生产流…

Jsch上传本地目录文件到服务器

文章目录 1.Jsch简介1.1 什么是Jsch1.2 Jsch使用步骤和简单示例 2.技术关键点3.Jsch实战3.1 maven依赖3.2 功能实现3.3 效果3.4 封装工具类 4.总结 摘要: 在一些框架开发工作中&#xff0c;需要为项目使用说明文档&#xff0c;来指导用户如何正确使用框架。比如通过markdown编写…

易舟云:让中小企业财务管理变得触手可及

在现代企业运营中&#xff0c;财务管理的精准和高效至关重要。对于中小企业来说&#xff0c;一款专业且易于使用的财务软件更是必不可少的工具。今天&#xff0c;我们就来详细了解一款深受中小企业喜爱的财务软件——易舟云。 财务管理的云端革命 随着云技术的发展&#xff0c;…

EVA-CLIP:在规模上改进CLIP的训练技术

摘要 对比性语言-图像预训练&#xff0c;简称CLIP&#xff0c;因其在各种场景中的潜力而备受关注。在本文中&#xff0c;我们提出了EVA-CLIP&#xff0c;一系列模型&#xff0c;这些模型显著提高了CLIP训练的效率和有效性。我们的方法结合了新的表示学习、优化和增强技术&…

Phaser-圆形路径

使用 Phaser 创建一个简单的路径动画 Phaser 是一个强大的 HTML5 游戏框架&#xff0c;适合用于开发 2D 游戏。在本文中&#xff0c;我们将展示如何使用 Phaser 创建一个简单的动画示例&#xff0c;其中一个红色的圆沿着椭圆路径移动。该示例将帮助你理解如何在 Phaser 中使用…

Linux用户,用户组,所有者权限分配,sftp用户权限分配

注意以下命令执行需要在root用户下执行 tenant命令切换至root命令 sudo -do root 删除用户信息 1.不删除用户主目录 userdel user_name 2.删除用户主目录 userdel -r user_name usermod命令修改用户账户权限 更改用户名 sudo usermod -l newusername oldusername 更…

Redis】Redis主从复制(二)————主从结构/流程

目录 回顾slaveof 命令断开主从复制关系切换主从复制关系只读网络延迟问题应对措施补充 主从结构一主一从结构问题改进 一主多从结构树形主从主从切换结构 主从复制流程简单来记关于数据同步两个参数replicationidoffset. psync 运行流程全量复制和部分复制全量复制流程&#x…

在镜像中添加Git提交号

文章目录 前言环境介绍思路内核cpuinfo中添加Git提交号修改setup.c获取Git提交号和生成GIT_COMMIT_INFO宏继续修改内核setup.c验证 内核设备树中添加Git提交号修改设备树验证 U-Boot版本号添加Git提交号U-Boot配置修改setlocalversion脚本验证 前言 在镜像中加入Git提交号&…

mysql和redis的双写一致性问题

一&#xff0c;使用方案 在使用redis作为缓存的场景下&#xff0c;我们一般使用流程如下 二&#xff0c;更新数据场景 我们此时修改个某条数据&#xff0c;如何保证mysql数据库和redis缓存中的数据一致呢&#xff1f; 按照常规思路有四种办法&#xff0c;1.先更新mysql数据&a…

计划任务!!!

目录 一、补充 1.1关闭防火墙 1.2安装php 二、计划任务 2.1at一次性计划任务 2.2周期性计划任务&#xff08;crontab&#xff09; 上篇我们学了rpm安装、yum安装还有编译安装。今天我们先补充一下上篇的东西再学习计划任务 一、补充 1.1关闭防火墙 systemctl stop fir…

亚马逊竞品分析之如何查找竞品

初选之后,要对产品进行竞品分析,查找竞品的方法: 1.Best Seller榜单查找 进入到该类目的BS榜单去找跟你选中的产品的竞品 看完BS榜单会找出一部分竞品 这个找相似也可以点击,是插件的一个以图搜图的功能,不过有的时候不太好使,某些同款产品可能搜不到。 Edge浏览器搭…