当前位置: 首页 > news >正文

Redis应用

问题

要保证 Redis 中存储的 20 万条数据始终是 MySQL 中 2000 万条数据中的热点数据

思路

1. **热点数据识别**:
   - 热点数据是指访问频率高的数据。需要一种机制来追踪和识别哪些数据是热点数据。
   
2. **数据同步机制**:
   - 当访问 MySQL 数据时,将热点数据写入 Redis,同时设置一个合理的过期时间。
   - 当 Redis 中的数据接近上限时(20 万条),需要通过一定的策略(如 LRU,即最近最少使用)删除不常访问的数据。

3. **Redis 的过期策略与淘汰策略**:
   - 使用 Redis 的内存淘汰策略(如 LRU、LFU)来自动删除不常访问的数据。
   - 设置合理的过期时间,定期清理长期未访问的数据。

4. **数据加载和更新**:
   - 每次查询数据时,先从 Redis 中查找,如果存在则直接返回;如果不存在,则从 MySQL 中查询,然后将数据写入 Redis。

 实现步骤

1. 设置 Redis 的淘汰策略为 LRU(最近最少使用),可以在 Redis 配置文件中设置 `maxmemory-policy` 为 `allkeys-lru`。
   
2. 在 Java 应用程序中,使用 Jedis 连接 Redis,使用 JDBC 连接 MySQL。

3. 实现一个数据查询方法,优先从 Redis 中获取数据,如果 Redis 中没有,再从 MySQL 中获取,并将其写入 Redis。

代码实现

   1. 添加依赖

如果您使用的是 Maven,请在 `pom.xml` 中添加以下依赖项:


<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.3.1</version>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.32</version>
</dependency>

代码实现


import redis.clients.jedis.Jedis;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Random;public class HotDataCaching {// Redis 连接配置private static final String REDIS_HOST = "localhost";private static final int REDIS_PORT = 6379;// MySQL 连接配置private static final String MYSQL_URL = "jdbc:mysql://localhost:3306/your_database";private static final String MYSQL_USER = "your_username";private static final String MYSQL_PASSWORD = "your_password";// Redis 缓存的最大容量private static final int REDIS_MAX_SIZE = 200000;// Jedis 客户端private Jedis jedis;// MySQL 连接private Connection mysqlConnection;public HotDataCaching() {// 初始化 Redis 连接jedis = new Jedis(REDIS_HOST, REDIS_PORT);try {// 初始化 MySQL 连接mysqlConnection = DriverManager.getConnection(MYSQL_URL, MYSQL_USER, MYSQL_PASSWORD);} catch (Exception e) {e.printStackTrace();}}/*** 从缓存(Redis)或数据库(MySQL)中获取数据*/public String getData(String key) {// 1. 从 Redis 获取数据String value = jedis.get(key);if (value != null) {System.out.println("从 Redis 中获取数据: " + value);return value;}// 2. 如果 Redis 中没有,则从 MySQL 中获取value = getDataFromMySQL(key);if (value != null) {// 将 MySQL 中获取的数据存入 RedissetDataToRedis(key, value);}return value;}/*** 从 MySQL 数据库中获取数据*/private String getDataFromMySQL(String key) {String query = "SELECT value FROM your_table WHERE key_column = ?";try (PreparedStatement stmt = mysqlConnection.prepareStatement(query)) {stmt.setString(1, key);ResultSet rs = stmt.executeQuery();if (rs.next()) {return rs.getString("value");}} catch (Exception e) {e.printStackTrace();}return null;}/*** 将数据存入 Redis*/private void setDataToRedis(String key, String value) {if (jedis.dbSize() >= REDIS_MAX_SIZE) {// Redis 中数据接近上限,采取措施(例如清理过期数据)System.out.println("Redis 缓存达到上限,准备清理过期数据...");}jedis.setex(key, 3600, value); // 设置 1 小时过期时间System.out.println("数据已存入 Redis,并设置过期时间为 1 小时: " + key);}public static void main(String[] args) {HotDataCaching cache = new HotDataCaching();// 模拟随机获取数据的操作Random random = new Random();for (int i = 0; i < 10; i++) {String key = "key" + random.nextInt(2000000); // 假设 MySQL 中有 2000 万条数据cache.getData(key);}// 关闭资源cache.closeConnections();}/*** 关闭 Redis 和 MySQL 连接*/private void closeConnections() {if (jedis != null) {jedis.close();}if (mysqlConnection != null) {try {mysqlConnection.close();} catch (Exception e) {e.printStackTrace();}}}
}

代码解释

1. **Redis 和 MySQL 连接初始化**:
   - 使用 Jedis 连接到 Redis 服务器,并使用 JDBC 连接到 MySQL 数据库。

2. **getData 方法**:
   - 首先从 Redis 中尝试获取数据,如果存在则直接返回。
   - 如果 Redis 中没有数据(即缓存未命中),则从 MySQL 数据库中获取数据,并将获取到的数据写入 Redis,同时设置过期时间(1 小时)。

3. **getDataFromMySQL 方法**:
   - 使用 JDBC 从 MySQL 数据库中查询数据,假设表结构中有 `key_column` 和 `value` 两个字段。

4. **setDataToRedis 方法**:
   - 在将数据写入 Redis 之前,检查 Redis 的当前数据量是否达到上限。如果达到上限,可以采取一些措施,比如清理过期数据或根据某些策略删除不常用的数据。
   - 使用 `jedis.setex` 方法将数据存入 Redis,并设置过期时间为 1 小时。

5. **数据模拟与连接关闭**:
   - 在 `main` 方法中,通过一个简单的循环模拟随机数据查询操作。
   - 程序结束时,关闭 Redis 和 MySQL 连接。

 Redis 配置

在 Redis 配置文件中,需要设置 Redis 的淘汰策略为 LRU。可以通过修改 `redis.conf` 文件来设置:

```conf
maxmemory 100mb  # 或者你希望的内存大小
maxmemory-policy allkeys-lru
```

- `maxmemory`:设置 Redis 最大可用内存。当内存达到限制时,Redis 会根据淘汰策略清理数据。
- `maxmemory-policy`:设置 Redis 的内存淘汰策略。`allkeys-lru` 表示在所有键中,移除最近最少使用的键。

总结

  1. 数据筛选:对MySQL中的数据进行筛选,只将热点数据存储到redis中。根据业务需求和数据特性,可以采用不同的策略进行筛选,例如按照访问频率、最近更新时间等进行排序,选择前20w条数据作为热点数据存储到redis中。

  2. 缓存更新策略:当MySQL中的数据发生变化时,及时更新redis中对应的数据。可以通过数据库触发器、消息队列等机制来捕捉数据变化,并将变化的数据同步到redis中,以保证redis中的数据与MySQL中的数据保持一致。

  3. 缓存淘汰策略:由于redis中存储的数据有限,当redis空间不足时,需要采取合适的缓存淘汰策略,优先保留热点数据。可以使用LRU(Least Recently Used)算法、LFU(Least Frequently Used)算法等来进行缓存淘汰,确保热点数据始终处于redis中。

  4. 预热机制:在系统启动时,可以提前将一部分热点数据加载到redis中,以减少后续访问时的延迟。可以通过定时任务或手动触发的方式进行预热操作,将MySQL中的热点数据主动加载到redis中。

  5. 使用缓存代理:可以借助缓存代理工具,如缓存云服务、Nginx等,将请求先发送到缓存代理,代理再判断是否命中缓存并返回结果。通过缓存代理层的缓存管理功能,可以更加灵活地控制热点数据的存储和更新。


http://www.mrgr.cn/news/10919.html

相关文章:

  • 等保测评与企业风险管理:构建坚实的信息安全防线
  • threejs 创建CSS3DSprite精灵标签, 可以更新位置及内容(封装)
  • 编程之路:在Bug的迷宫中寻找出口
  • 【限时秒杀】基于SpringBoot+Vue的智慧旅游攻略系统+LW示例参考
  • 二分查找算法:朴素二分+左右边界二分力扣实战应用
  • 邻接表的具体实例
  • bat 文件, 简化git 操作
  • QT通过信号传递参数至槽函数(不通层级通信)
  • 如何使用ssm实现基于ssm的“游侠”旅游信息管理系统
  • MySql【数据查询语言DQL】
  • 生产环境中MapReduce的最佳实践
  • 消息队列MQ
  • Large Bin Attack 源码调试
  • 爬虫使用代理IP:提升数据抓取效率的实践
  • React 入门第一天:从Vue到React的初体验
  • ECharts tooltip默认html样式,保留样式只对数据数值格式化
  • 数据结构之串与KMP算法详解
  • OpenCV杂项图像变换(2)线性混合函数blendLinear()的使用
  • npm install常见错误以及解决办法
  • 巴西游戏出海!Bigo Ads助力巴西休闲游戏APP营销广告策略