使用Spring4.3解决缓存过期后多线程并发访问数据库的问题
来源:互联网 发布:博科光交双端口级联 编辑:程序博客网 时间:2024/06/06 02:31
缓存过期之后,如果多个线程同时请求对某个数据的访问,会同时去到数据库,导致数据库瞬间负荷增高。Spring4.3为@Cacheable注解提供了一个新的参数“sync”(boolean类型,缺省为false),当设置它为true时,只有一个线程的请求会去到数据库,其他线程都会等待直到缓存可用。这个设置可以减少对数据库的瞬间并发访问。
不过不一定所有的缓存系统都支持这个配置。经过验证,Guava Cache是支持的。验证过程如下:
1、Guava Cache配置,参考:http://blog.csdn.net/clementad/article/details/51250472
4、测试结果:
当设置3个并发线程的时候,会出现3个log:“getting data from database, userId=26358”,说明访问了3次数据库。
当修改注解如下之后,只出现一次“getting data from database, userId=26358”,说明只访问了1次数据库,另外两次命中了缓存:
不过不一定所有的缓存系统都支持这个配置。经过验证,Guava Cache是支持的。验证过程如下:
1、Guava Cache配置,参考:http://blog.csdn.net/clementad/article/details/51250472
2、创建从数据库获取数据的类和方法,该方法使用@Cacheable注解:
@Servicepublic class UserServiceCacheablesImpl implements UserServiceCacheables{private final static Logger logger = LoggerFactory.getLogger(UserServiceCacheablesImpl.class);@AutowiredUserDAO userDAO;@Override@Cacheable(value="getPhoneNoByUserId")public String getPhoneNoByUserId(int userId) {logger.debug("getting data from database, userId={}", userId);return userDAO.getPhoneNoByUserId(userId);}}
3、创建多线程并发的单元测试代码:
@RunWith(SpringRunner.class)@SpringBootTestpublic class AdminApplicationTests {protected final Logger logger = LoggerFactory.getLogger(this.getClass());@AutowiredUserServiceCacheables userServiceCacheables;/** * 多线程并发测试 */@Testpublic void multiThreads() throws Exception{int number = 3; //线程数ExecutorService executorService = Executors.newFixedThreadPool(number);List<Future<String>> results = new ArrayList<Future<String>>();int userId = 26358;for (int i=0; i < number; i++) { //非阻塞地启动number个线程,由Future接收结果Future<String> future = executorService.submit(new MyThread(userId));//Thread.sleep(300);results.add(future);}for(Future<String> f : results){ //从Future中获取结果,打印出来String phoneNo = f.get();logger.debug(phoneNo);}}class MyThread implements Callable<String>{int userId;public MyThread(int userId) {this.userId = userId;}@Overridepublic String call() throws Exception {return userServiceCacheables.getPhoneNoByUserId(userId);}}}
4、测试结果:
当设置3个并发线程的时候,会出现3个log:“getting data from database, userId=26358”,说明访问了3次数据库。
当修改注解如下之后,只出现一次“getting data from database, userId=26358”,说明只访问了1次数据库,另外两次命中了缓存:
@Cacheable(value="getPhoneNoByUserId", sync=true)
2 0
- 使用Spring4.3解决缓存过期后多线程并发访问数据库的问题
- 使用ThreadLocal解决多线程的并发问题
- 使用ThreadLocal解决多线程的并发问题
- 使用ThreadLocal解决多线程的并发问题
- 使用ThreadLocal解决多线程的并发问题
- 解决多线程并发访问SQLite数据库
- memcache解决高并发高访问的数据库瓶颈问题
- 利用Memcache解决数据库高并发访问的瓶颈问题
- memcache解决高并发高访问的数据库瓶颈问题
- 用Memcache解决数据库高并发访问的瓶颈问题
- 利用Memcache解决数据库高并发访问的瓶颈问题
- 利用Memcache解决数据库高并发访问的瓶颈问题
- 访问数据库时如何解决并发问题
- 解决数据库高并发访问瓶颈问题
- php 使用redis锁解决并发访问的问题
- 使用redis解决一些并发访问的问题
- 使用ThreadLocal解决多线程程序并发问题
- 解决多线程并发问题
- RxJava之条件和布尔操作符
- 引用与指针的区别
- 第二周项目--汉诺塔实验
- UIView动画与core animation之间的关系
- 转载:Cxf webservice Can't find the request for **'s Observer
- 使用Spring4.3解决缓存过期后多线程并发访问数据库的问题
- Unix网络编程(卷一)-第一个简单的时间获取程序
- 使用tornado实现定时执行任务
- LeetCode: Linked List Cycle II
- 建议46:显式释放资源需继承接口IDisposable
- mvc APi 找到了与该请求匹配的多个操作
- 搭建高可用mongoDB集群
- ACM大赛排名问题 之 竞赛排行榜
- 自识别标记(self-identifying marker) -(4) 用于相机标定的CALTag源码剖析(下)