springboot整合redis 解决热数据查询mysql数据库的导致io问题(初级开发工程师必看)

1、springboot整合redis

Jedis的作用

	Jedis是基于Java语言的Redis的客户端,Jedis = Java + RedisRedis不仅可以使用命令来操作,现在基本上主流的语言都有API支持,比如JavaC#、C++PHPNode.js、Go等。在官方网站里有一些Java的客户端:JedisRedissonJredisJDBC-Redis等,其中官方推荐使用JedisRedisson。简言之JedisRedisJava版本API,通过使用Jedis可以操作Redis中的数据。	
	jedis连接资源的创建与销毁是很消耗程序性能,所以jedis为我们提供了jedis的连接池技术,jedis
连接池在创建时初始化一些连接对象存储到连接池中,使用jedis连接资源时不需要自己创建jedis对象,而是从连接池中获取一个资源进行redis的操作。使用完毕后,不需要销毁该jedis连接资源,而是将该资源归还给连接池,供其他请求使用。

pom坐标的引入:

	 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.8.1</version>
        </dependency>

yml文件的配置:

spring:
  redis: ##单机部署的话 需要使用下面的配置
    host: localhost
    password: 123456
    timeout: 6000
    port: 6379
    jedis:
      pool:
        max-active: 8 # 最大连接
        max-idle: 8 # 最大空闲连接
        min-idle: 0 # 最小空闲连接
        max-wait: 100ms # 连接等待时间

config配置类bean的配置

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        // 创建模板
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        // 设置连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // 设置序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer =
                new GenericJackson2JsonRedisSerializer();
        // key和 hashKey采用 string序列化
        redisTemplate.setKeySerializer(RedisSerializer.string());
        redisTemplate.setHashKeySerializer(RedisSerializer.string());
        // value和 hashValue采用 JSON序列化
        redisTemplate.setValueSerializer(jsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jsonRedisSerializer);
        return redisTemplate;
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // 配置序列化(解决乱码的问题),过期时间600秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }

}

2、将热数据进行设置到缓存中

要将热数据设置到缓存中,可以按照以下步骤操作:

1. 选择一个适合的缓存系统:选择一个适合你的需求的缓存系统,常见的缓存系统有RedisMemcached等。

2. 安装和配置缓存系统:按照缓存系统的官方文档,下载、安装和配置缓存系统。确保缓存系统能正常运行。

3. 编写代码连接缓存系统:使用编程语言连接到缓存系统,并确保能够正确地与缓存系统进行通信。

4. 设计缓存策略:根据热数据的特点和业务需求,设计一个适合的缓存策略。可以考虑使用LRU(最近最少使用)或LFU(最近最不常用)等缓存淘汰算法。

5. 将热数据设置到缓存中:根据缓存策略,将热数据设置到缓存中。可以通过缓存系统提供的API,将数据存储到缓存中。

6. 读取缓存中的数据:在需要读取热数据的地方,先尝试从缓存中读取数据。如果缓存中存在数据,则直接使用缓存中的数据。如果缓存中不存在数据,则从数据库或其他持久化存储中读取数据,并将数据存储到缓存中,以便下次使用。

7. 更新缓存中的数据:当热数据发生变化时,及时更新缓存中的数据。可以通过缓存系统提供的API,更新缓存中的数据。

通过以上步骤,你可以将热数据设置到缓存中,提高系统的读取性能和响应速度。

3、缓存击穿和雪崩问题的处理

缓存击穿是指在某个时间点,缓存中的某个数据过期了,同时又有大量的并发请求过来访问该数据,导致请求都落到了数据库上,造成数据库压力过大,甚至宕机的情况。

雪崩问题是指在某个时间点,缓存中的大部分数据同时过期,而且此时又有大量的并发请求过来访问这些数据,导致所有请求都落到了数据库上,造成数据库压力过大,甚至宕机的情况。

针对缓存击穿和雪崩问题,可以采取以下一些处理方式:

1. 设置合理的缓存过期时间:避免缓存过期时间集中在一个时间点,导致缓存大规模同时失效。

2. 使用互斥锁(mutex)或分布式锁:在缓存失效的时候,通过加锁的方式,只允许一个线程去访问数据源,而其他线程需要等待,避免了大量的并发请求落到数据库上。

3. 提前进行缓存预热:在缓存即将过期之前,提前主动刷新缓存,避免缓存失效期间的并发请求落到数据库上。

4. 使用熔断机制:在缓存失效期间,如果数据库压力过大,可以暂时屏蔽该服务,避免影响到其他服务。

5. 数据库优化:通过优化数据库性能,提高数据库的并发处理能力,减少数据库宕机的风险。

6. 限流降级:对并发请求进行限流,避免大量请求同时访问数据库,可以使用限流工具、负载均衡等方式。

总的来说,处理缓存击穿和雪崩问题需要综合考虑缓存设置、锁机制、缓存预热、熔断机制、数据库优化等多个方面的因素,根据具体情况采取适当的措施。

4、将一些重要的数据进行持久化

持久化数据是指将数据保存在存储介质上,以便在程序终止后仍然能够保留数据。以下是一些常见的持久化数据的方法:

1. 文件存储:将数据以文件的形式保存在磁盘上。可以使用文本文件、二进制文件或者特定格式的文件(如JSONXML等),根据需求选择合适的文件格式。读写文件可以使用文件操作的API,如打开、写入和读取文件的操作。

2. 数据库存储:将数据保存在关系型数据库(如MySQLOracle等)或非关系型数据库(如MongoDBRedis等)中。使用数据库可以更方便地对数据进行增删改查的操作,并且支持复杂的查询功能。

3. 缓存存储:将数据保存在缓存中,以加快访问速度。常见的缓存存储方式有内存缓存(如Redis)和分布式缓存(如Memcached)。

4. 对象持久化:将对象保存在持久化存储中,以保留对象的状态。可以使用对象持久化框架(如Hibernate)将对象映射到数据库中,并提供相应的操作方法。

5. 日志存储:将重要的数据写入日志文件中,以便后续分析和查看。可以使用日志框架(如Log4j)将日志信息输出到文件或者其他目标(如控制台、数据库等)。

需要根据具体需求和项目特点选择合适的持久化方案,并根据数据的重要程度和访问频率来确定持久化的策略。

5、数据一致性问题

数据一致性问题是指在分布式系统中,由于多个节点间的异步通信、并发操作等原因导致数据在不同节点间的不一致现象。

在分布式系统中,由于网络延迟、通信故障等原因,不同节点上的数据可能会有一定的延迟或不一致。例如,在一个分布式数据库系统中,当一个客户端在一个节点上执行了一个写操作,并且马上又执行了一个读操作,由于数据复制的延迟,读操作可能会读取到旧的数据,导致数据不一致。

数据一致性问题还会出现在并发写操作的情况下。当多个客户端同时对同一份数据进行写操作时,如果不加控制,可能会导致数据的覆盖或冲突,进而引发数据一致性问题。

为了解决数据一致性问题,可以采取以下几种措施:

1. 引入分布式事务:通过分布式事务管理器来保证多个节点上的操作的一致性,确保数据的正确更新。

2. 使用乐观锁和悲观锁:乐观锁使用版本号或时间戳来解决并发写操作的冲突问题,悲观锁通过加锁的方式来保证数据的一致性。

3. 使用分布式缓存:通过将数据缓存在分布式缓存中,可以降低对数据库的读写操作,并减少数据不一致的可能性。

4. 引入副本机制:将数据复制到多个节点上,通过复制机制来确保数据的一致性。

5. 采用一致性哈希算法:通过一致性哈希算法来分布数据到多个节点上,避免节点的增减对数据一致性产生影响。

总之,数据一致性问题是分布式系统设计中需要解决的重要问题,需要通过合适的技术手段来保证数据的一致性。
  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
要实现Spring Boot整合RedisMySQL,并将数据MySQL导入Redis,可以按照以下步骤进行: 1. 在pom.xml文件中添加RedisMySQL的依赖。 2. 在application.properties文件中配置RedisMySQL的连接信息。 3. 创建一个RedisConfig类,用于配置RedisTemplate。 4. 创建一个MySQLConfig类,用于配置DataSource和JdbcTemplate。 5. 创建一个Service类,用于从MySQL中读取数据,并将数据存储到Redis中。 6. 在Controller中调用Service类中的方法,从Redis中读取数据并返回给前端。 下面是一个简单的示例代码: 1. pom.xml文件中添加RedisMySQL的依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> ``` 2. application.properties文件中配置RedisMySQL的连接信息: ``` # Redis spring.redis.host=localhost spring.redis.port=6379 # MySQL spring.datasource.url=jdbc:mysql://localhost:3306/test spring.datasource.username=root spring.datasource.password=root ``` 3. 创建一个RedisConfig类,用于配置RedisTemplate: ``` @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return template; } } ``` 4. 创建一个MySQLConfig类,用于配置DataSource和JdbcTemplate: ``` @Configuration public class MySQLConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource dataSource() { return DataSourceBuilder.create().build(); } @Bean public JdbcTemplate jdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); } } ``` 5. 创建一个Service类,用于从MySQL中读取数据,并将数据存储到Redis中: ``` @Service public class UserService { private final JdbcTemplate jdbcTemplate; private final RedisTemplate<String, Object> redisTemplate; public UserService(JdbcTemplate jdbcTemplate, RedisTemplate<String, Object> redisTemplate) { this.jdbcTemplate = jdbcTemplate; this.redisTemplate = redisTemplate; } public List<User> getAllUsers() { List<User> users = jdbcTemplate.query("SELECT * FROM user", new BeanPropertyRowMapper<>(User.class)); users.forEach(user -> redisTemplate.opsForValue().set("user:" + user.getId(), user)); return users; } } ``` 6. 在Controller中调用Service类中的方法,从Redis中读取数据并返回给前端: ``` @RestController public class UserController { private final UserService userService; public UserController(UserService userService) { this.userService = userService; } @GetMapping("/users") public List<User> getAllUsers() { List<User> users = (List<User>) userService.redisTemplate.opsForValue().get("users"); if (users == null) { users = userService.getAllUsers(); userService.redisTemplate.opsForValue().set("users", users); } return users; } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

QD_IT伟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值