`
xly_971223
  • 浏览: 1276771 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

帖子 博客等资源点击量缓存杀手级解决方案

    博客分类:
  • java
阅读更多
标题党了 

关于点击量几年前发过帖子http://www.iteye.com/topic/171240
现在看来太简单了 而且问题多多

最近有琢磨出了一套新的方案

进入正题

关于帖子点击量,通常的办法是缓存在内存,然后等到合适的时机写入数据库,一般是设置一个阈值,到达后更新数据库
这种方式主要面临如下几个问题:
1 有些帖子永远到达不了阈值怎么办?如阈值为10,但到9后再也没有人点击了
2 阈值设置多大合适?太大了服务器当机会丢失大量数据,太小了没啥意义
3 每个帖子到达阈值后都要访问数据库,能不能合并起来 只访问一次DB

采用阈值方式是被动的,应该用主动的方式来解决问题
主动方式的思路如下:cache ---》 文件 ---》DB
1 cache中保存两个点击量,我们称之为todayHits和yestodayHits
todayHits保存资源当天的点击量
yestodayHits保存昨天的点击量

2 定时把cache中发生变化的数据导出到文件,未发生变化的删除
3 把导出的文件导入到数据库。多数DB都提供命令. mysql 为 load data local infile
此方法是把文件中的数据追加到表尾,这样会导致一个资源对应多个点击量的问题,我们用导入时间获取最新的点击量
4 删除过期数据。每次追加后会使原来部分数据变得无意义,需要清理掉
主动方式会定时扫描cache中数据

空说太抽象 直接上代码
不重要的方法省略
设计Cahce的key和value
HitKey 封装了资源id和资源类型
public final class HitKey implements Serializable {
	private Integer id;
	private HitType type;
//setter getter ...
}


/**
 * 保存资源的点击量
 * @author xuliangyong
 * 2009-7-12
 */
public class HitValue implements Serializable {
	/**
	 * 今天的总点击量
	 */
	private Integer todayHits;
	/**
	 * 昨天的总点击量
	 */
	private Integer yestodayHits;
	
	public HitValue(){}
	
	private HitValue(Integer todayHits, Integer yestodayHits){
		this.todayHits = todayHits;
		this.yestodayHits = yestodayHits;
	}
	
	/**
	 * 工厂方法
	 */
	public static HitValue valueOf(Integer todayHits, Integer yestodayHits){
		return new HitValue(todayHits, yestodayHits);
	}
	
	/**
	 * 增加点击次数
	 * @param hit 点击次数
	 * @return 返回总点击次数
	 */
	public void addHits(Integer hit){
		if(todayHits == null){
			todayHits = new Integer(0);
		}
		todayHits += hit;
	}
	
	/**
	 * 点击次数加1
	 * @return 返回总点击次数
	 */
	public void addHits(){
		addHits(1);
	}
	
	/**
	 * 把昨天点击量与今天点击量同步。
	 * 此方法通常在写完日志文件后调用
	 */
	public void synchronize(){
		yestodayHits = todayHits;
	}
	
	/**
	 * 测试点击量是否变化。
	 */
	public boolean isChanged(){
		return yestodayHits != todayHits;
	}
	
}



用一个Map做cache,可更换成第三方缓存,最好是有region概念的缓存
public class HitsFacade {
	
	private static final Map<HitKey, HitValue>  HITS_CACHE = Collections.synchronizedMap(new HashMap<HitKey, HitValue>());
	
	private HitsManager hitsManager;
	
	/**
	 * 获取资源点击量.
	 * 1 从cache读 
	 * 2 从持久存储读
	 */
	public Integer get(HitKey hitKey){
		HitValue hitValue = HITS_CACHE.get(hitKey);
		
		if(hitValue == null){
			Integer hits = getHits(hitKey);
			hitValue = HitValue.valueOf(hits, hits);
			HITS_CACHE.put(hitKey, hitValue);
		}
		
		return hitValue.getTodayHits();
	}
	
	/**
	 * 增加1次点击量
	 * 用法:
	 * hitsFacade.add( HitKey.valueOf(blogId, HitType.BLOG) );
	 * @param hitKey
	 */
	public void add(HitKey hitKey){
		add(hitKey, 1);
	}
	
	/**
	 * 增加点击量
	 * 用法:
	 *  hitsFacade.add( HitKey.valueOf(blogId, HitType.BLOG), 10 );
	 * @param hits 增加的次数
	 */
	public void add(HitKey hitKey, Integer hits){
		HitValue hitValue = HITS_CACHE.get(hitKey);
		if(hitValue == null){
			get(hitKey);
			hitValue = HITS_CACHE.get(hitKey);
		}
		
		hitValue.addHits(hits);
		HITS_CACHE.put(hitKey, hitValue);
	}
	
	/**
	 * 从持久存储加载点击量。
	 * 为避免并发导致多次访问持久存储,故加synchronized关键字
	 */
	//TODO 并发如何处理??
	protected synchronized Integer getHits(HitKey hitKey) {
		return hitsManager.getHits(hitKey);
	}
}


至此cache代码处理完毕

接下来处理cache ---》 文件
	/**
	 * 把hits cache中的数据导出到日志文件
	 */
	public File exportHitsCacheToLog() throws IOException{
		Map<HitKey, HitValue> hitsCache = hitsFacade.getCache();
		Iterator<HitKey> hitKeyIterator = hitsCache.keySet().iterator();
		
		//创建文件
		File logFile = createFile();
		BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(logFile));
		
		while (hitKeyIterator.hasNext()) {
			HitKey hitKey = hitKeyIterator.next();
			HitValue hitValue = hitsCache.get(hitKey);

			if( !hitValue.isChanged() ){
				hitKeyIterator.remove();
			}else{
				StringBuilder sb = new StringBuilder();
				sb.append(hitKey.getId()).append("\t")
					.append(hitKey.getType()).append("\t")
					.append(hitValue.getTodayHits()).append("\t")
					.append(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"))
					.append("\n");
				bufferedWriter.write(sb.toString());
				
				hitValue.synchronize();
				hitsCache.put(hitKey, hitValue);
			}
		}
		
		//关闭文件
		bufferedWriter.flush();
		bufferedWriter.close();
		return logFile;
	}


此方法是核心 尤其是这几句
if( !hitValue.isChanged() ){
//如果今天的数据相比昨天无变化则删除
				hitKeyIterator.remove();
			}else{
				StringBuilder sb = new StringBuilder();
				sb.append(hitKey.getId()).append("\t")
					.append(hitKey.getType()).append("\t")
					.append(hitValue.getTodayHits()).append("\t")
					.append(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"))
					.append("\n");
				bufferedWriter.write(sb.toString());
				//有今天的数据相比昨天发生变化则写入文件,并把昨天的数据与今天同步
				hitValue.synchronize();
				hitsCache.put(hitKey, hitValue);
			}


再接下来 文件 ----》DB
为什么要从文件导入DB而不直接从cache写入DB呢 请参考http://xuliangyong.iteye.com/admin/blogs/424921
importDB("load data local infile '" + path + "' into table " + tableName);


最后为清理过期的无效数据,此过程可另找时间清理 不必与上述步骤同步进行

该缓存方案已初步完成,随着项目的变化也会做相应调整
到底性能如何 能否应付海量数据 还有待检验

2009-09-20 补充
最后一步清理过期数据 采用了新的方法
使用
load data local infile ... replace into ...

这样会自动覆盖掉旧点击次数,也就无需清理无效数据了


分享到:
评论
46 楼 C_J 2009-08-12  
我晕了,有那么复杂吗??


把几千条insert放在一个transaction,1次commit不就完事了么?
45 楼 pocketduck 2009-07-27  
luoli-17 写道
xly_971223 写道
wulinux 写道
xly_971223 写道
wulinux 写道
用JMS解决呀。
当前端更新了以后, 把变化的内容用JMS的形式发送到后台。后台线程接受到后,更新数据库。 这个过程不需要同步,可以允许有滞后。这样可以非常有效的解决你数据库服务器的压力。数据库更新成功后发一个JMS到缓存系统,把原来的数据清除掉,重新从数据库读出数据。我觉得这样可以解决你的问题了。




jms确实可以降低服务器的瞬间压力,实际上却没有节省资源
我的方案更强调的是节省资源


你的提法确实可以节省资源,但是你可以保证你的机器不崩溃吗? 如果系统死了,你前面9次修改的东西都丢失了,你的用户是否可以接受呢?

说的没错 这也是我一直担心的问题,要解决这个问题就扯出缓存事务了  那问题就搞复杂了

另外 像点击量这种不是特别重要的数据有点偏差也是可以的


我们做程序的讲究的是思想的严密性,像你说的不是特别重要的数据有点偏差也是可以的。这种想法是绝对不能存在的。假设我们将你的方案移植到银行或者金融类的程序开发中,不是特别危险了?什么是程序设计?一个好的程序至少应该在设计上是严密的,而不是以一种侥幸的心理以阿Q式方式去安慰自己,这种情况是很少存在的。做程序员千万要杜绝这种思想的出现。

你说的太教条主义了,没错做程序员的要讲究的是思想的严密性,但是要结合需求来考虑,从需求来说,有的要求不能有任何误差,比如银行,但是显然lz的这种需求就是不要求绝对正确的,往往有很多业务,从技术上就是无法做到绝对准确的,所以你说的一大堆未免教条主义了
44 楼 luoli-17 2009-07-25  
superscorpio 写道
xly_971223 写道
srdrm 写道
用得着这么复杂吗, 我定个时间, 每隔30分钟将所有贴子的hits缓存刷到数据库中, 或者10分钟. 或者, 任意定个时间, 至少能解决绝大部分问题

如果缓存了10w帖子 假设有1w个发生了变化
你刷到数据库看看 1W条sql几乎同时到服务器不搞死才怪

10w对一个网站来说是非常小的数目了 如果是100W 1000W呢?



你怎么会缓存那么多帖子呢? 我觉得这才是最大的不合理!


这种情况还是存在的,前段时间百度贴吧里面炒的很热的一篇帖子“贾君鹏你妈妈喊你回家吃饭”在短短的几天时间里回帖就达到了30多万。可想而知互联网这玩意儿什么情况都是会存在的。我们更不应该以合理不合理去思考互联网。
43 楼 luoli-17 2009-07-25  
xly_971223 写道
wulinux 写道
xly_971223 写道
wulinux 写道
用JMS解决呀。
当前端更新了以后, 把变化的内容用JMS的形式发送到后台。后台线程接受到后,更新数据库。 这个过程不需要同步,可以允许有滞后。这样可以非常有效的解决你数据库服务器的压力。数据库更新成功后发一个JMS到缓存系统,把原来的数据清除掉,重新从数据库读出数据。我觉得这样可以解决你的问题了。




jms确实可以降低服务器的瞬间压力,实际上却没有节省资源
我的方案更强调的是节省资源


你的提法确实可以节省资源,但是你可以保证你的机器不崩溃吗? 如果系统死了,你前面9次修改的东西都丢失了,你的用户是否可以接受呢?

说的没错 这也是我一直担心的问题,要解决这个问题就扯出缓存事务了  那问题就搞复杂了

另外 像点击量这种不是特别重要的数据有点偏差也是可以的


我们做程序的讲究的是思想的严密性,像你说的不是特别重要的数据有点偏差也是可以的。这种想法是绝对不能存在的。假设我们将你的方案移植到银行或者金融类的程序开发中,不是特别危险了?什么是程序设计?一个好的程序至少应该在设计上是严密的,而不是以一种侥幸的心理以阿Q式方式去安慰自己,这种情况是很少存在的。做程序员千万要杜绝这种思想的出现。
42 楼 a376730551 2009-07-25  
缓存内存+定时更新怎么样啊
41 楼 xly_971223 2009-07-24  
superscorpio 写道
xly_971223 写道
srdrm 写道
量或许是很大, 但一天之内有hit的贴子量不会是这种100w量级的, 10w量级的贴子更新数我认为对于网站来说不小了. 刷到数据库不一定要同时刷, 这个不要求即时的,可以悠着点来,怎么悠怎么来,只要在一个合理时间内完成就行


sorry 怪我前面没讲清除
这里缓存的不仅仅是帖子的点击量,还包括博客 相片 新闻 圈子 等等吧 所有这些点击量都是缓存在一起的
对一般的网站这个量还是不小的


楼主兄弟,用缓存的原因能给我解释一下吗?我非常好奇!

点击量那个问题,楼上各位都提出了方案。


减少访问数据库次数
40 楼 superscorpio 2009-07-24  
xly_971223 写道
srdrm 写道
量或许是很大, 但一天之内有hit的贴子量不会是这种100w量级的, 10w量级的贴子更新数我认为对于网站来说不小了. 刷到数据库不一定要同时刷, 这个不要求即时的,可以悠着点来,怎么悠怎么来,只要在一个合理时间内完成就行


sorry 怪我前面没讲清除
这里缓存的不仅仅是帖子的点击量,还包括博客 相片 新闻 圈子 等等吧 所有这些点击量都是缓存在一起的
对一般的网站这个量还是不小的


楼主兄弟,用缓存的原因能给我解释一下吗?我非常好奇!

点击量那个问题,楼上各位都提出了方案。
39 楼 superscorpio 2009-07-24  
xly_971223 写道
srdrm 写道
用得着这么复杂吗, 我定个时间, 每隔30分钟将所有贴子的hits缓存刷到数据库中, 或者10分钟. 或者, 任意定个时间, 至少能解决绝大部分问题

如果缓存了10w帖子 假设有1w个发生了变化
你刷到数据库看看 1W条sql几乎同时到服务器不搞死才怪

10w对一个网站来说是非常小的数目了 如果是100W 1000W呢?



你怎么会缓存那么多帖子呢? 我觉得这才是最大的不合理!
38 楼 xly_971223 2009-07-24  
引用

使用libevent/mina+bdb可以实现高效的点击服务器
bdb可配置增大内存cache
另外开发一套bdb备份恢复数据的程序可解决bdb文件崩溃的问题

跟据生产环境的真实数据,libevent+bdb方案,一台机器可以支撑600W的pv
如果pv继续增大,可考虑对key做hash,分部到n台机器上

看来得学习一下libevent了
37 楼 woodless 2009-07-24  
potian 写道
根本没必要搞这么复杂,一个关键字/值数据库就足矣

一两行代码的问题

即使需要简单的查询操作也可以胜任

所有不需要要计入关系模型的,不需要进行复杂统计的,都可以这样做,包括用户的最后点击时间等等

持续每秒钟几万次的更新轻而易举

tokyotyrant,bdb都可以



同意

使用libevent/mina+bdb可以实现高效的点击服务器
bdb可配置增大内存cache
另外开发一套bdb备份恢复数据的程序可解决bdb文件崩溃的问题

跟据生产环境的真实数据,libevent+bdb方案,一台机器可以支撑600W的pv
如果pv继续增大,可考虑对key做hash,分部到n台机器上
36 楼 menuhin 2009-07-24  
不管楼主有没有必要做的这么复杂,但是我觉得楼主给我们提供的这个思路还是不错的!
35 楼 pocketduck 2009-07-23  
potian 写道
xly_971223 写道
potian 写道
根本没必要搞这么复杂,一个关键字/值数据库就足矣

一两行代码的问题

即使需要简单的查询操作也可以胜任

所有不需要要计入关系模型的,不需要进行复杂统计的,都可以这样做,包括用户的最后点击时间等等

持续每秒钟几万次的更新轻而易举

tokyotyrant,bdb都可以



tokyotyrant中文文档貌似比较少
bdb倒是可以尝试一下


真当是晕倒了,就是启动一下,写一两行代码的问题,为什么还需要很多中文文档

何况作为一个程序员,看几句英语都吃不消

bdb写个网络接口也是很简单的事情,用libevent或者eventmachine或者什么java网络框架都可以呀

对只用过一种主流语言的程序员来说,你这个建议等于没说一下,只能让人更崩溃
34 楼 whaosoft 2009-07-23  
redis  ?我都不知道 lz 这个好用么 给讲讲
33 楼 binlaniua 2009-07-22  
厄 等待更详细的解说
32 楼 xly_971223 2009-07-22  
potian 写道
xly_971223 写道
potian 写道
根本没必要搞这么复杂,一个关键字/值数据库就足矣

一两行代码的问题

即使需要简单的查询操作也可以胜任

所有不需要要计入关系模型的,不需要进行复杂统计的,都可以这样做,包括用户的最后点击时间等等

持续每秒钟几万次的更新轻而易举

tokyotyrant,bdb都可以



tokyotyrant中文文档貌似比较少
bdb倒是可以尝试一下


真当是晕倒了,就是启动一下,写一两行代码的问题,为什么还需要很多中文文档

何况作为一个程序员,看几句英语都吃不消

bdb写个网络接口也是很简单的事情,用libevent或者eventmachine或者什么java网络框架都可以呀


大侠就是不一样 啥都能写 

能不能写一个学习一下
31 楼 potian 2009-07-22  
xly_971223 写道
potian 写道
根本没必要搞这么复杂,一个关键字/值数据库就足矣

一两行代码的问题

即使需要简单的查询操作也可以胜任

所有不需要要计入关系模型的,不需要进行复杂统计的,都可以这样做,包括用户的最后点击时间等等

持续每秒钟几万次的更新轻而易举

tokyotyrant,bdb都可以



tokyotyrant中文文档貌似比较少
bdb倒是可以尝试一下


真当是晕倒了,就是启动一下,写一两行代码的问题,为什么还需要很多中文文档

何况作为一个程序员,看几句英语都吃不消

bdb写个网络接口也是很简单的事情,用libevent或者eventmachine或者什么java网络框架都可以呀
30 楼 xly_971223 2009-07-22  
看了一下Berkeley DB
Berkeley DB多应用于嵌入式场景 在java中是跑在jvm里面的,就是说其数据不能在多台机器间共享
这一特点决定了其不能应用于集群环境中
也就不适合大多数的互联网项目

火星的redis 这里有一篇介绍 http://www.iteye.com/topic/350595
29 楼 xly_971223 2009-07-22  
potian 写道
根本没必要搞这么复杂,一个关键字/值数据库就足矣

一两行代码的问题

即使需要简单的查询操作也可以胜任

所有不需要要计入关系模型的,不需要进行复杂统计的,都可以这样做,包括用户的最后点击时间等等

持续每秒钟几万次的更新轻而易举

tokyotyrant,bdb都可以



tokyotyrant中文文档貌似比较少
bdb倒是可以尝试一下
28 楼 potian 2009-07-22  
根本没必要搞这么复杂,一个关键字/值数据库就足矣

一两行代码的问题

即使需要简单的查询操作也可以胜任

所有不需要要计入关系模型的,不需要进行复杂统计的,都可以这样做,包括用户的最后点击时间等等

持续每秒钟几万次的更新轻而易举

tokyotyrant,bdb都可以

27 楼 kjskbh 2009-07-22  
xly_971223 写道
icefishc 写道
xly_971223 写道

麻烦仁兄帮测一下行不 


我的测试结果是相差6倍左右.(myisam 和 innodb 都是这样) 
不管是向空表中插还是向非空表中插入随即数据结果差不多都是这个数.

我是在一个虚拟机上测的..... 也许不太靠谱......


感谢 icefishc

我刚才又换了台机器测试了一下
表结构 innodb 无主键
CREATE TABLE `sns_hits` (
  `resource_id` int(11) default NULL,
  `resource_type` varchar(20) default NULL,
  `hits` int(11) default NULL,
  `create_time` datetime default NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


批量插入java代码

long start = System.currentTimeMillis();
			conn.setAutoCommit(false);
			ps = conn.prepareStatement("insert into sns_hits values(?,?,?,?)");
			for(int i = 0; i < 100000; i++){
				ps.setInt(1, 1);
				ps.setString(2, "BLOG");
				ps.setInt(3, 34);
				ps.setString(4, "2009-07-23 18:23:20");
				ps.addBatch();//加入批处理
			}
			int[] results = ps.executeBatch();//执行批处理
			conn.commit();
			System.out.println(System.currentTimeMillis() - start);


数据文件 都是同样的数据
1	BLOG	34	2009-07-23 18:23:20
1	BLOG	34	2009-07-23 18:23:20
1	BLOG	34	2009-07-23 18:23:20
1	BLOG	34	2009-07-23 18:23:20
1	BLOG	34	2009-07-23 18:23:20


数据库没有调整任何参数,即使调整估计影响也不大
      1W   5W  10W
PreparedStatement        1828/1704   8172/7892       16125/15734(ms) 
load data local infile   219/234/156     1187/610/688    968/1141  (ms) 

斜杠'/'分割多次测试
                                                   
平均在10倍左右

看来这玩意受硬件的影响比较大 跟上次测试比较http://xuliangyong.iteye.com/blog/424921
分别插入 1W 5W 10W 结果如下
PreparedStatement        1953   9203  17641(ms) 
load data local infile   125    625   1172  (ms) 



那是肯定和硬件相关度大的,数据库增删改最终还是要通过IO操作写到磁盘里的

相关推荐

    MysqL缓存的解决方案

    "MySQL缓存的解决方案" MySQL 缓存是提高数据库性能的一种重要手段,它可以减少数据库的读写次数,从而提高系统的整体性能。以下将对 MySQL 缓存的解决方案进行详细的介绍。 缓存的必要性 缓存的主要目的是减少...

    缓存一致性问题与解决方案

    锁在多线程环境下用于解决资源竞争问题,但并不能解决缓存一致性问题。因为锁只能确保在某一时刻只有一个线程访问数据,但无法保证所有线程都能看到最新的数据状态。 2. **消息中间件**: 单纯的消息中间件可以...

    2023.09-2024.09期间《天翼云高级解决方案架构师参考题库》

    《天翼云高级解决方案架构师参考题库》涵盖了IT基础设施、云服务管理、高可用性设计、网络资源、教育云解决方案以及高校上云等多个领域的知识。以下是对这些知识点的详细阐述: 1. IT基础设施通常由计算、存储和...

    麒逸信息互联网缓存加速解决方案PPT

    麒逸信息互联网缓存加速解决方案,视频缓存,HTTP缓存

    nginx静态文件缓存的解决方案1

    【Nginx 静态文件缓存解决方案】 Nginx 是一款高性能的 HTTP 和反向代理服务器,常用于处理静态资源,以减轻后端服务器的压力。为了进一步提高静态资源的访问效率,我们可以利用 Nginx 的缓存功能。下面详细介绍...

    js,css缓存杀手——VS插件

    总之,“js,css缓存杀手——VS插件”是解决浏览器缓存问题的有效工具,它能帮助开发者更高效地管理和更新前端资源,确保代码的实时更新和网站的正常运行。通过熟练掌握并运用这类插件,开发者可以提升工作效率,提供...

    如何设计缓存系统:缓存穿透,缓存击穿,缓存雪崩解决方案分析.docx

    缓存系统设计解决方案分析 缓存系统是当前web应用程序中最常用的性能...缓存系统设计需要考虑的要素很多,但是如果我们采用合适的解决方案,可以避免缓存穿透、缓存雪崩和缓存击穿等问题,提高系统的性能和可靠性。

    深入理解MyBatis中的一级缓存与二级缓存

    "深入理解MyBatis中的一级缓存与二级缓存" MyBatis是一种流行的持久层框架,它提供了缓存机制来提高应用程序的性能。在MyBatis中,有两种类型的缓存:一级缓存和二级缓存。下面我们将深入了解MyBatis中的一级缓存和...

    Android代码-web资源的本地缓存方案

    CandyWebCache是移动端web资源的本地缓存解决方案,能够拦截webview的请求,并优先使用本地缓存静态资源进行响应,以此来对webview加载页面性能进行优化。 特点: 协议层拦截请求,透明替换响应 静态资源版本控制及...

    WebView的缓存方案:H5缓存机制 + 资源预加载 + 资源拦截.zip

    方案是为解决特定问题或达成特定目标而制定的一系列计划或步骤。它的作用是提供一种系统性的方法,以有效地应对挑战、优化流程或实现目标。以下是方案的主要作用: 问题解决: 方案的核心目标是解决问题。通过系统...

    高效的缓存管理解决方案AutoLoadCache.zip

    现在使用的缓存技术很多,比如Redis、 Memcache 、 EhCache等,甚至还有使用ConcurrentHashMap 或 HashTable 来实现缓存。但在缓存的使用上,每个人都有自己的实现方式,大部分是直接与业务代码绑定,随着业务...

    基于Java和Redis的shiro缓存集中式解决方案设计源码

    shiro缓存集中式解决方案项目源码,共63个文件,全部采用Java语言编写,涉及多种文件类型如Java源代码、XML配置文件、LICENSE文件、Markdown文档、PNG图片、INI配置文件等。该项目是一个基于Java和Redis的shiro缓存...

    缓存穿透,缓存击穿,缓存雪崩解决方案分析.docx

    缓存穿透、缓存击穿、缓存雪崩解决方案分析 本文主要介绍了缓存系统中三个常见的问题:缓存穿透、缓存击穿和缓存雪崩,并对每个问题提供了多种解决方案。 缓存穿透 缓存穿透是指查询一个一定不存在的数据,由于...

    chrome缓存资源导出工具

    Chrome缓存资源导出工具正是为了解决这个问题。通过使用这款工具,用户无需具备高级的技术知识,就能简单地查看和提取Chrome的缓存数据。例如,如果你是一个网站开发者,可能需要检查某个网页在用户端的加载情况,...

    hibernate一级缓存和二级缓存的区别与联系

    二级缓存可以通过设置不同的并发访问策略来解决并发问题,如事务型、读写型或非严格读写型,以适应不同场景下的需求。 持久化层的缓存范围决定了缓存的生命周期和访问权限。事务范围的缓存最安全,但只限于当前事务...

    HTML,JSP页面缓存的解决方案

    ### HTML与JSP页面缓存解决方案 在Web开发过程中,页面缓存问题一直是开发者们关注的重点之一。合理的页面缓存管理不仅可以提升用户体验,还可以减轻服务器压力。然而,在某些情况下,如模态窗口中的POSTBACK操作时...

Global site tag (gtag.js) - Google Analytics