# 客户数据预加载解决方案 ## 一、当前系统性能问题分析 ### 1. 数据加载模式 - **请求-响应模式**:当前系统使用传统的请求-响应模式,每次前端请求数据时,后端才会查询数据库并返回结果 - **多次数据库查询**:单个客户数据请求涉及多个数据库查询(基本信息、联系人、购物车项、负责人等) - **缺少缓存机制**:系统中没有实现任何缓存机制,所有数据都直接从数据库查询 - **前端频繁请求**:作为客户关系管理系统,前端需要频繁请求客户数据 ### 2. 性能瓶颈 - **数据库查询开销大**:每次请求都需要执行多次数据库查询 - **网络延迟**:频繁的HTTP请求导致网络延迟累积 - **数据重复传输**:相同数据可能被多次请求和传输 - **缺少数据预加载**:没有在用户需要之前预先加载数据 ## 二、预加载解决方案设计 ### 1. 后端预加载策略 #### 1.1 添加缓存层 - **使用Redis作为缓存存储**:高性能、高可用的键值存储 - **实现数据预加载服务**:定期将热点数据加载到缓存中 - **合理设置过期时间**:根据数据类型和更新频率设置不同的过期时间 #### 1.2 优化数据库查询 - **实现数据预聚合**:减少查询次数,提高查询效率 - **使用JOIN查询**:替代多次单表查询,减少数据库交互次数 - **添加索引优化**:为频繁查询的字段添加索引 #### 1.3 实现数据预加载服务 - **定时任务预加载**:定期预加载热点数据 - **数据变更监听**:当数据发生变化时及时更新缓存 - **分层预加载**:为不同类型的用户预加载不同的数据 ### 2. 前端预加载策略 #### 2.1 实现前端缓存 - **使用localStorage/sessionStorage**:缓存不经常变化的数据 - **数据预加载机制**:在用户访问页面之前加载数据 - **数据过期机制**:定期更新缓存,确保数据新鲜度 #### 2.2 优化请求策略 - **请求合并**:减少HTTP请求次数 - **请求预加载**:在用户可能访问的数据之前加载 - **懒加载**:只加载当前需要的数据,减少初始加载时间 #### 2.3 WebSocket实时更新 - **建立WebSocket连接**:实现数据实时更新 - **后端主动推送**:当数据发生变化时,主动推送给前端 - **减少轮询请求**:降低服务器压力,提高响应速度 ## 三、具体实施方案 ### 1. 后端实现 #### 1.1 添加Redis依赖 ```xml org.springframework.boot spring-boot-starter-data-redis ``` #### 1.2 配置Redis连接 ```yaml # application.yaml spring: redis: host: localhost port: 6379 password: database: 0 ``` #### 1.3 实现缓存服务 ```java // CacheService.java @Service public class CacheService { @Autowired private RedisTemplate redisTemplate; // 缓存数据 public void cacheData(String key, Object data, long expireTime, TimeUnit timeUnit) { redisTemplate.opsForValue().set(key, data, expireTime, timeUnit); } // 获取缓存数据 public T getCachedData(String key, Class clazz) { Object data = redisTemplate.opsForValue().get(key); return clazz.cast(data); } // 删除缓存数据 public void deleteCachedData(String key) { redisTemplate.delete(key); } // 检查缓存是否存在 public boolean isCached(String key) { return redisTemplate.hasKey(key); } } ``` #### 1.4 实现数据预加载服务 ```java // PreloadService.java @Service public class PreloadService { @Autowired private UsersMapper usersMapper; @Autowired private CacheService cacheService; // 预加载热点客户数据 - 每5分钟执行一次 @Scheduled(fixedRate = 300000) public void preloadHotCustomers() { List hotCustomers = usersMapper.selectHotCustomers(); for (UserProductCartDTO customer : hotCustomers) { String key = "customer:" + customer.getUserId(); cacheService.cacheData(key, customer, 1, TimeUnit.HOURS); } } // 预加载客户列表数据 - 每10分钟执行一次 @Scheduled(fixedRate = 600000) public void preloadCustomerList() { List customerList = usersMapper.selectAllCustomers(); cacheService.cacheData("customer:list", customerList, 30, TimeUnit.MINUTES); } } ``` #### 1.5 修改服务层代码,使用缓存 ```java // CustomerService.java @Service public class CustomerService { @Autowired private UsersMapper usersMapper; @Autowired private CacheService cacheService; // 获取客户数据,优先从缓存获取 public UserProductCartDTO getCustomerById(String userId) { String cacheKey = "customer:" + userId; // 尝试从缓存获取 UserProductCartDTO customer = cacheService.getCachedData(cacheKey, UserProductCartDTO.class); if (customer != null) { return customer; } // 缓存未命中,从数据库查询 customer = usersMapper.selectById(userId); // 将查询结果存入缓存 if (customer != null) { cacheService.cacheData(cacheKey, customer, 1, TimeUnit.HOURS); } return customer; } } ``` #### 1.6 实现数据变更监听 ```java // DataChangeAspect.java @Aspect @Component public class DataChangeAspect { @Autowired private CacheService cacheService; // 监听数据更新方法,清除相关缓存 @AfterReturning(pointcut = "execution(* com.example.web.service.*Service.update*(..))") public void afterUpdate(JoinPoint joinPoint) { // 清除相关缓存 Object[] args = joinPoint.getArgs(); for (Object arg : args) { if (arg instanceof UserProductCartDTO) { UserProductCartDTO customer = (UserProductCartDTO) arg; String cacheKey = "customer:" + customer.getUserId(); cacheService.deleteCachedData(cacheKey); } // 清除客户列表缓存 cacheService.deleteCachedData("customer:list"); } } } ``` ### 2. 前端实现 #### 2.1 前端预加载逻辑 ```javascript // 在mainapp-sells.html和mainapp-supplys.html中添加 // 预加载客户数据 function preloadCustomerData() { // 预加载客户列表 fetch('/api/customers/list') .then(response => response.json()) .then(data => { if (data.success) { // 将数据存入localStorage localStorage.setItem('customerList', JSON.stringify(data.data)); localStorage.setItem('customerListExpire', Date.now() + 30 * 60 * 1000); // 30分钟过期 } }); // 预加载热点客户数据 fetch('/api/customers/hot') .then(response => response.json()) .then(data => { if (data.success) { // 将数据存入localStorage localStorage.setItem('hotCustomers', JSON.stringify(data.data)); localStorage.setItem('hotCustomersExpire', Date.now() + 60 * 60 * 1000); // 1小时过期 } }); } // 页面加载完成后预加载数据 window.addEventListener('load', preloadCustomerData); // 在用户可能访问的页面之前预加载数据 document.addEventListener('click', function(e) { if (e.target.matches('[data-preload]')) { const preloadUrl = e.target.getAttribute('data-preload'); fetch(preloadUrl) .then(response => response.json()) .then(data => { // 将数据存入sessionStorage sessionStorage.setItem(preloadUrl, JSON.stringify(data)); }); } }); ``` #### 2.2 前端缓存读取逻辑 ```javascript // 获取客户数据,优先从缓存读取 function getCustomerData(userId) { // 尝试从localStorage获取 const cachedData = localStorage.getItem('customerList'); const expireTime = localStorage.getItem('customerListExpire'); if (cachedData && expireTime && Date.now() < parseInt(expireTime)) { const customerList = JSON.parse(cachedData); const customer = customerList.find(c => c.userId === userId); if (customer) { return Promise.resolve(customer); } } // 缓存未命中,从服务器获取 return fetch(`/api/customers/${userId}`) .then(response => response.json()) .then(data => { if (data.success) { return data.data; } throw new Error(data.message); }); } ``` ## 四、预期效果 ### 1. 性能提升 - **数据加载速度**:预计提升50%-90% - **数据库查询次数**:预计减少60%-80% - **前端响应时间**:预计提升40%-70% - **服务器压力**:预计降低50%-70% ### 2. 用户体验改善 - **页面加载更快**:减少用户等待时间 - **数据响应更迅速**:提升系统交互流畅度 - **减少页面卡顿**:优化数据加载机制 - **支持更多并发用户**:提高系统吞吐量 ## 五、实施步骤 1. **安装并配置Redis服务器** 2. **添加Redis依赖和配置** 3. **实现缓存服务和预加载服务** 4. **修改现有服务层代码,使用缓存** 5. **实现数据变更监听** 6. **修改前端代码,实现预加载和缓存** 7. **测试和优化** ## 六、注意事项 1. **数据一致性**:确保缓存数据与数据库数据的一致性 2. **缓存过期策略**:根据数据更新频率设置合理的过期时间 3. **内存管理**:监控Redis内存使用情况,避免内存溢出 4. **错误处理**:实现缓存失效时的降级策略 5. **性能监控**:添加性能监控,持续优化系统性能 ## 七、总结 本预加载解决方案通过引入缓存机制和预加载策略,将有效解决当前系统数据加载慢的问题。通过后端预加载热点数据到Redis缓存,前端预加载和缓存数据,以及实现数据变更监听,系统的数据加载速度将得到显著提升,同时降低数据库压力和网络延迟,改善用户体验。 该方案具有良好的扩展性和可维护性,可以根据系统的实际运行情况进行调整和优化,为系统的长期稳定运行提供保障。