精华内容
下载资源
问答
  • 正在运行进程:需要占用一定的cpu资源RAM(内存)空间,多少的话看是什么应用,要消耗一定的电量,影响手机速度等性能。 后台缓存进程:不需要占用cpu资源,会在RAM中写入一部分数据,当下次打开这个应用时会...

    正在运行的进程:需要占用一定的cpu资源和RAM(内存)空间,多少的话看是什么应用,要消耗一定的电量,影响手机速度等性能。

    后台缓存的进程:不需要占用cpu资源,会在RAM中写入一部分数据,当下次打开这个应用时会快一些,当然也会占用一点内存,如果手机内存够大对速度性能不会有影响,如果内存不够那么会触发android的内存回收机制,优先杀掉这些进程(和java的垃圾回收机制相似),会耗一点点电,几乎没什么影响,只是在内存的某些位上写了地址数据,每隔一段时间过一遍电脉冲,刷新来保持数据。

    转载于:https://www.cnblogs.com/homg/p/3345022.html

    展开全文
  • android获取当前设备运行app的进程

    千次阅读 2017-11-13 23:49:35
    进程优先级从高到低可分为四种:前台进程、可视进程、服务进程、缓存进程。 前台进程(foreground process):用户当前正在进行可操作的,一般满足以下条件: (1).屏幕顶层运行Activity(处于onResume()状态),...

    1.当前设备进程分类

    进程优先级从高到低可分为四种:前台进程可视进程服务进程缓存进程

    前台进程(foreground process)用户当前正在进行可操作的,一般满足以下条件:

    (1).屏幕顶层运行Activity(处于onResume()状态),用户正与之交互。

    (2).有BroadcastReceiver正在执行代码。

    (3).有Service在其回调方法(onCreate()、onStart()、onDestroy())中正在执行代码。

    可视进程(visible process):做用户当前意识到的工作。一般满足以下条件:

    (1).屏幕上显示Activity,但不可操作(处于onPause()状态)。

    (2).有service通过调用Service.startForeground(),作为一个前台服务运行。

    (3).含有用户意识到的特定的服务,如动态壁纸、输入法等 

    服务进程(service process):含有以startService()方法启动的service。虽然该进程用户不直接可见,

    但是它们一般做一些用户关注的事情(如数据的上传与下载)。这些进程一般不会杀死,除非系统内存不足以

    保持前台进程和可视进程的运行。 对于长时间运行的service(如30分钟以上),系统会考虑将之降级为缓存进程,

    避免长时间运行导致内存泄漏或其他问题,占用过多RAM以至于系统无法分配充足资源给缓存进程。

    缓存/后台进程(cached/background process):一般来说包含以下条件:

    (1). 包含多个Activity实例,但是都不可见(处于onStop()且已返回)。 
    系统如有内存需要,可随意杀死。

    2.android SDK版本20以下获取当前进程

    在android5.0即sdk20以下,获取当前进程需要在注册权限,权限为:

    	android.Manifest.permission.GET_TASKS
    获取之前先判断权限是否已注册:

    	/**
    	 * 检查当前应用是否有指定的权限
    	 * 
    	 * @param context
    	 * @param permName
    	 *            --权限
    	 * @return true--有, false--没有
    	 */
    	public static boolean checkPermission(Context context, String permName) {
    		PackageManager pm = context.getPackageManager();
    		if (PackageManager.PERMISSION_GRANTED == pm.checkPermission(permName, context.getPackageName())) {
    			return true;
    		}
    		return false;
    	}
    最后获取当前进程包名:

    	/**
    	 * 获取当用户在试用的应用包名,适用于5.0以下
    	 * 
    	 * @param context
    	 * @return
    	 */
    	public static String getRunningTask(Context context) {
    		ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    		List<RunningTaskInfo> taskInfos = am.getRunningTasks(1);
    		if (taskInfos != null && taskInfos.size() > 0) {
    			ComponentName cn = taskInfos.get(0).topActivity;
    			return cn.getPackageName();
    		}
    		return "";
    	}

    在android5.0即sdk20以上(包含20),要获取当前设备进程,用常规方式只能获取自身应用,若自身应用不是前台进程,者获取不到其他进程包名。以下方式是通过读取系统进程底层文件来获取当前进程包名。

    /**
    	 * 获取当用户在试用的应用包名,适用于5.0以上
    	 * 
    	 * @return
    	 */
    	public static String getForegroundApp(Context context) {
    		File[] files = new File("/proc").listFiles();
    		int lowestOomScore = Integer.MAX_VALUE;
    		String foregroundProcess = null;
    		for (File file : files) {
    			if (!file.isDirectory()) {
    				continue;
    			}
    			int pid;
    			try {
    				pid = Integer.parseInt(file.getName());
    			} catch (NumberFormatException e) {
    				continue;
    			}
    			try {
    				String cgroup = read(String.format("/proc/%d/cgroup", pid));
    				String[] lines = cgroup.split("\n");
    				String cpuSubsystem;
    				String cpuaccctSubsystem;
    
    				if (lines.length == 2) {// 有的手机里cgroup包含2行或者3行,我们取cpu和cpuacct两行数据
    					cpuSubsystem = lines[0];
    					cpuaccctSubsystem = lines[1];
    				} else if (lines.length == 3) {
    					cpuSubsystem = lines[0];
    					cpuaccctSubsystem = lines[2];
    				} else if (lines.length == 5) {
    					cpuSubsystem = lines[2];
    					cpuaccctSubsystem = lines[4];
    				} else {
    					continue;
    				}
    				if (!cpuaccctSubsystem.endsWith(Integer.toString(pid))) {
    					continue;
    				}
    				if (cpuSubsystem.endsWith("bg_non_interactive")) {
    					continue;
    				}
    				String cmdline = read(String.format("/proc/%d/cmdline", pid));
    				if (isContainsFilter(cmdline)) {
    					continue;
    				}
    				int uid = Integer.parseInt(cpuaccctSubsystem.split(":")[2].split("/")[1].replace("uid_", ""));
    				if (uid >= 1000 && uid <= 1038) {
    					continue;
    				}
    				int appId = uid - AID_APP;
    				while (appId > AID_USER) {
    					appId -= AID_USER;
    				}
    				if (appId < 0) {
    					continue;
    				}
    				File oomScoreAdj = new File(String.format("/proc/%d/oom_score_adj", pid));
    				if (oomScoreAdj.canRead()) {
    					int oomAdj = Integer.parseInt(read(oomScoreAdj.getAbsolutePath()));
    					if (oomAdj != 0) {
    						continue;
    					}
    				}
    				int oomscore = Integer.parseInt(read(String.format("/proc/%d/oom_score", pid)));
    				if (oomscore < lowestOomScore) {
    					lowestOomScore = oomscore;
    					foregroundProcess = cmdline;
    				}
    				if (foregroundProcess == null) {
    					return null;
    				}
    				int indexOf = foregroundProcess.indexOf(":");
    				if (indexOf != -1) {
    					foregroundProcess = foregroundProcess.substring(0, indexOf);
    				}
    			} catch (NumberFormatException e) {
    				e.printStackTrace();
    			} catch (IOException e) {
    				e.printStackTrace();
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		}
    		return foregroundProcess;
    	}
    	private static String read(String path) throws IOException {
    		StringBuilder output = new StringBuilder();
    		BufferedReader reader = new BufferedReader(new FileReader(path));
    		output.append(reader.readLine());
    
    		for (String line = reader.readLine(); line != null; line = reader.readLine()) {
    			output.append('\n').append(line);
    		}
    		reader.close();
    		return output.toString().trim();// 不调用trim(),包名后会带有乱码
    	}
    有一些应用是常驻应用包名,添加过滤方法:

    	/**
    	 * filter包名过滤
    	 * 
    	 * @param cmdline
    	 * @return
    	 */
    	public static boolean isContainsFilter(String cmdline) {
    		boolean flag = false;
    		if (filterMap == null || filterMap.isEmpty() || filterMap.size() == 0) {
    			initFliter();
    		}
    		if (filterMap != null) {
    			for (String key : filterMap.keySet()) {
    				if (cmdline.contains(key)) {
    					flag = true;
    					break;
    				}
    			}
    		}
    		return flag;
    	}
    下面方法是判断是否为第三方应用,并且有界面的应用:

    	/**
    	 * 判断是否为第三方应用,并且有界面的应用
    	 * 
    	 * @param context
    	 * @param packageName
    	 * @return true:第三方应用,并且有界面
    	 */
    	public static boolean isUserApp(Context context, String packageName) {
    		List<String> names = new ArrayList<String>();
    		PackageManager packageManager = context.getPackageManager();
    		Intent intent = new Intent(Intent.ACTION_MAIN);
    		intent.addCategory(Intent.CATEGORY_HOME);
    		List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);//
    		for (ResolveInfo resolveInfo : list) {
    			names.add(resolveInfo.activityInfo.packageName);
    		}
    		if (!names.contains(packageName)) {
    			if (packageManager.getLaunchIntentForPackage(packageName) != null) {
    				return true;
    			}
    		}
    		return false;
    	}
    下面方法是判断是否为桌面应用:

    	/**
    	 * 是否为桌面应用
    	 * 
    	 * @param context
    	 * @param packageName
    	 * @return
    	 */
    	public static boolean isLauncherApp(Context context, String packageName) {
    		List<String> names = new ArrayList<String>();
    		PackageManager packageManager = context.getPackageManager();
    		Intent intent = new Intent(Intent.ACTION_MAIN);
    		intent.addCategory(Intent.CATEGORY_HOME);
    		List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);//
    		for (ResolveInfo resolveInfo : list) {
    			names.add(resolveInfo.activityInfo.packageName);
    		}
    		if (names.contains(packageName)) {
    			return true;
    		}
    		return false;
    	}
    有一些第三方常驻顶层应用,可以在初始化的时候添加进去,比如:
    	/**
    	 * 初始化filter
    	 */
    	public static void initFliter() {
    		if (filterMap == null) {
    			filterMap = new HashMap<String, Integer>();
    		}
    		if (filterMap.isEmpty() || filterMap.size() == 0) {
    			filterMap.put("com.android.systemui", 0);
    			filterMap.put("com.aliyun.ams.assistantservice", 0);
    			filterMap.put("com.meizu.cloud", 0);
    			filterMap.put("com.android.incallui", 0);
    			filterMap.put("com.amap.android.location", 0);
    			filterMap.put("com.android.providers.contacts", 0);
    			filterMap.put("com.samsung.android.providers.context", 0);
    			filterMap.put("com.android.dialer", 0);
    			filterMap.put("com.waves.maxxservice", 0);
    			filterMap.put("com.lge.camera", 0);
    			filterMap.put("se.dirac.acs", 0);
    			filterMap.put("/", 0);
    		}
    	}
    转载请说明出处:http://blog.csdn.net/u012438830/article/details/78526152
    下面是本人的具体代码事例代码,需要的到请下载
    点击打开链接







    展开全文
  • springboot2+ehcache集成攻略与教程,,,先来看看ehcache缓存与redis缓存的区别 ...- redis是通过`socket`访问到缓存服务,效率比ecache低,比数据库要快很多,处理集群分布式缓存方便,有成熟的方案。。。

    在这里插入图片描述
    官网对ehcache的描述是:

    Ehcache is an open source, standards-based cache that boosts performance, offloads your database, and simplifies scalability. It’s the most widely-used Java-based cache because it’s robust, proven, full-featured, and integrates with other popular libraries and frameworks. Ehcache scales from in-process caching, all the way to mixed in-process/out-of-process deployments with terabyte-sized caches.

    Ehcache是一个基于标准的开源缓存,可提高性能,减轻数据库负载并简化可伸缩性。 它是最广泛使用的基于Java的缓存,因为它健壮,可靠,功能齐全并与其他流行的库和框架集成。 Ehcache可以从进程内缓存扩展到具有TB级别缓存的混合进程内/进程外部署。

    ehcache特性

    • 快速、简单,纯Java的进程缓存框架
    • 快速集成,与springboot、hibernate等框架很友好
    • 多种缓存策略:LRU(最近最少使用算法,默认策略)、FIFO(先进先出)、LFU(最不经常使用策略)
    • 缓存数据有两级:内存和磁盘,因此无需担心内部不够或者内存爆掉问题
    • 缓存数据可以设置在虚拟机重启的过程中写入磁盘
    • 具有缓存和缓存管理器的侦听接口
    • 支持多缓存管理器实例,以及一个实例的多个缓存区域

    ehcache缓存与redis缓存的区别

    • ehcache直接在jvm虚拟机/java进程中缓存,可以理解为缓存在内存中,速度快,效率高;但是缓存共享麻烦,集群分布式应用不方便。可以直接单独使用,集成于项目内,一般在第三方库中被用到的比较多(如mybatis、shiro等),多用于内部缓存 ,或者一般没有微服务的单实例小项目。
    • redis是通过socket访问到缓存服务,效率比ecache低,比数据库要快很多,处理集群和分布式缓存方便,有成熟的方案。
    • 两者可以配合使用,ehcache做项目内部缓存 ,redis做分布式缓存。如果是单个应用或者对缓存访问要求很高的应用,用ehcache。如果是大型系统,存在缓存共享、分布式部署、缓存内容很大的,建议用redis。简单的讲,小项目/单例/不需节点同步的缓存 >直接ehcache大项目/微服务/分布式/性能/管理 >直接reids
    • 如果强行要搞分布式和缓存共享(不建议),ehcache也有缓存共享方案,不过是通过RMI或者Jgroup多播方式进行广播缓存通知更新,缓存共享复杂,维护不方便;简单的共享可以,但是涉及到缓存恢复,大数据缓存,则不合适。

    开源项目

    1024程序员节快乐!

    以下demo代码已经上传到 spring-cloud-study学习项目 https://github.com/moshowgame/spring-cloud-studyspring-cloud-study-ehcache 模块
    在这里插入图片描述

    大家可以自由下载、改进、讨论与学习!你的进步也是我的进步,你的意见和留言是我前进的动力!

    pom.xml:依赖引入

    	<dependencies>
    		
    		<!-- SpringBoot缓存支持启动器 -->
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-cache</artifactId>
    		</dependency>
    
    		<!-- Ehcache基础包 -->
    		<dependency>
    			<groupId>javax.cache</groupId>
    			<artifactId>cache-api</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.ehcache</groupId>
    			<artifactId>ehcache</artifactId>
    		</dependency>
    
    	</dependencies>
    

    Application.java:加@EnableCaching开启缓存

    @EnableCaching为Spring Cache的注解,使用后缓存功能生效,否则无效。

    package com.softdev.system.demo;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cache.annotation.EnableCaching;
    
    @SpringBootApplication
    @EnableCaching
    public class EmptyApplication {
    	public static void main(String[] args) {
    		SpringApplication.run(EmptyApplication.class,args);
    	}
    }
    
    

    ehcache.xml:缓存策略配置

    新建一个ehcache.xml与application.yml项目配置文件同级,也就是在src/main/resources/下。

    默认情况下ehcache会自动加载 classpath 根目录下名为ehcache.xml文件,也可以将该文件放到其他地方并在使用时指定文件的位置。
    在这里插入图片描述

    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
             updateCheck="false">
        <!--
          powered by zhengkai.blog.csdn.net
    
          diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下:
          user.home – 用户主目录
          user.dir  – 用户当前工作目录
          java.io.tmpdir – 默认临时文件路径
    
          defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。
          name:缓存名称。
          maxElementsInMemory:缓存最大数目
          maxElementsOnDisk:硬盘最大缓存个数。
          eternal:对象是否永久有效,一但设置了,timeout将不起作用。
          overflowToDisk:是否保存到磁盘,当内存中Element数量达到maxElementsInMemory时,Ehcache将会Element写到磁盘中
          timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
          timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
          diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
          diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
          diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
          memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
          clearOnFlush:内存数量最大时是否清除。
          memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用算法,默认策略)、FIFO(先进先出)、LFU(最不经常使用策略)。
          FIFO,first in first out,先进先出策略。
          LFU, Less Frequently Used,最不经常使用策略。缓存的元素有一个hit计数属性,hit值最小的将会被清出缓存。
          LRU,Least Recently Used,最近最少使用策略(LRU)是大部分操作系统为最大化页面命中率而广泛采用的一种页面置换算法。该算法的思路是,选择未使用且时间最长的缓存移除掉。
       -->
        <diskStore path = "Java.io.tmpdir/tmp_ehcache"/>
        <defaultCache
                eternal="false"
                maxElementsInMemory="10000"
                overflowToDisk="false"
                diskPersistent="false"
                timeToIdleSeconds="1800"
                timeToLiveSeconds="259200"
                memoryStoreEvictionPolicy="LRU"/>
    
        <cache
                name="zhengkai.blog.csdn.net"
                eternal="false"
                maxElementsInMemory="10000"
                overflowToDisk="false"
                diskPersistent="false"
                timeToIdleSeconds="1800"
                timeToLiveSeconds="1800"
                memoryStoreEvictionPolicy="LRU"/>
    </ehcache>
    

    参数详解:

    • diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下:
    • user.home – 用户主目录
    • user.dir – 用户当前工作目录
    • java.io.tmpdir – 默认临时文件路径-
    • defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。
    • name:缓存名称。
    • maxElementsInMemory:缓存最大数目
    • maxElementsOnDisk:硬盘最大缓存个数。
    • eternal:对象是否永久有效,一但设置了,timeout将不起作用。
    • overflowToDisk:当内存中Element数量达到maxElementsInMemory时,Ehcache将会Element写到磁盘中
    • timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
    • timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
    • diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
    • diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
    • diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
    • memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
    • clearOnFlush:内存数量最大时是否清除。
    • memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用算法,默认策略)、FIFO(先进先出)、LFU(最不经常使用策略)。
    • FIFO,first in first out,先进先出策略。
    • LFU, Less Frequently Used,最不经常使用策略。缓存的元素有一个hit计数属性,hit值最小的将会被清出缓存。
    • LRU,Least Recently Used,最近最少使用策略(LRU)是大部分操作系统为最大化页面命中率而广泛采用的一种页面置换算法。该算法的思路是,选择未使用且时间最长的缓存移除掉。

    application.yml:设置缓存区名称

    这里我设置了两个缓存区,例如我给证书查询系统设置缓存:

    • cache-certList , 证书列表 ,用于缓存单个证书的详情,变动比较多,一有编辑就更新指定id的记录。
    • cache-certType , 证书分类,用于缓存证书分类,一般很久才会变,一有编辑就清空所有缓存记录重新来过。
    server:
      port: 9999
      servlet:
          context-path: /ehcache
    spring:
        http:
          encoding:
            force: true
            charset: UTF-8
        application:
            name: spring-cloud-study-ehcache
        cache:
          cache-names:
            - cache-certList
            - cache-certType
    

    Entity:定义测试实体

    package com.softdev.system.demo.entity;
    import lombok.Data;
    import java.io.Serializable;
    @Data
    public class Cert implements Serializable {
        Integer certId;
        String certNumber;
    }
    
    @Data
    public class CertType implements Serializable {
        Integer typeId;
        String typeName;
        String certNumberPrefix;
    
        public CertType(Integer typeId, String typeName, String certNumberPrefix) {
            this.typeId = typeId;
            this.typeName = typeName;
            this.certNumberPrefix = certNumberPrefix;
        }
    }
    
    

    Controller:进行缓存

    这里用 Controlle 层做缓存,但是实际上建议在Service或者Repository / Mapper层做缓存,也可以设置一个CacheUtil来设置缓存的id等,然后再设置一个CacheService来设置一些全局缓存。
    无论你在哪一层,只要加上注释,马上成!

    • @Cacheable(value = "cache-certList", key = "#cert.certId") 保存指定的id到缓存。
    • @CacheEvict(value = "cache-certList", key = "#cert.certId") 使指定id的缓存失效。
    • @CacheEvict(value = "cache-certType" , allEntries=true) 使所有缓存都失效,清空该缓存区/组。
    package com.softdev.system.demo.controller;
    
    import com.alibaba.fastjson.JSON;
    import com.softdev.system.demo.entity.Cert;
    import com.softdev.system.demo.entity.CertType;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.cache.annotation.CacheEvict;
    import org.springframework.cache.annotation.Cacheable;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.ArrayList;
    import java.util.List;
    /**
     * EhCache缓存控制器demo
     * @author zhengkai.blog.csdn.net
     * */
    @Slf4j
    @RestController
    public class DemoController {
    
        @GetMapping("")
        public ResponseEntity<String> index(){
            return ResponseEntity.ok("请求成功");
        }
    
        @RequestMapping("cert/save")
        @CacheEvict(value = "cache-certList", key = "#cert.certId")
        public Cert save(Cert cert){
            log.info("保存cert到数据库:"+ JSON.toJSONString(cert));
            return cert;
        }
        @Cacheable(value = "cache-certList", key = "#cert.certId")
        @RequestMapping("cert/find")
        public Cert find(Cert cert){
            log.info("从数据库中读取cert:"+ JSON.toJSONString(cert));
            return cert;
        }
        @RequestMapping("type/all")
        @CacheEvict(value = "cache-certType")
        public List<CertType> getType(){
            List<CertType> list = new ArrayList<>();
            list.add(new CertType(1,"个人证书","csdn-person"));
            list.add(new CertType(2,"企业证书","csdn-enterprise"));
            list.add(new CertType(3,"云证书","csdn-cloud"));
            log.info("从数据库中读取typeList:"+ JSON.toJSONString(list));
            return list;
        }
        @CacheEvict(value = "cache-certType" , allEntries=true)
        @RequestMapping("type/clean")
        public List<CertType> clean(){
            log.info("清理所有typeList缓存");
            return null;
        }
    }
    
    

    请求URL :开始缓存,校验缓存

    1. 先查询数据 http://localhost:9999/ehcache/cert/find?certId=1&certNumber=111111,首次调用控制台会输出 从数据库中读取cert:{"certId":1,"certNumber":"111111"} (因为我们没有数据库,这里模拟从数据库中读取数据出来的感觉)
      在这里插入图片描述
      在这里插入图片描述

    2. 继续查看证书,连续调用多次,看控制台输出,没有新的日志生成,代表成功 http://localhost:9999/ehcache/cert/find?id=1
      在这里插入图片描述

    3. 尝试能否修改缓存中的信息,不可能的,修改失败
      在这里插入图片描述

    4. save接口修改缓存 http://localhost:9999/ehcache/cert/save?certId=1&certNumber=3333 (save方法会让缓存失效,重新查询则会重新获取并缓存)
      在这里插入图片描述

    5. 再次进行缓存 http://localhost:9999/ehcache/cert/find?certId=1&certNumber=3333
      在这里插入图片描述

    6. 再次验证缓存 http://localhost:9999/ehcache/cert/find?certId=1
      在这里插入图片描述

    @Cacheable:使用缓存

    @Cacheable可以标记在一个方法上,也可以标记在一个类上。当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。对于一个支持缓存的方法,Spring会在其被调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。Spring在缓存方法的返回值时是以键值对进行缓存的,值就是方法的返回结果,至于键的话,Spring又支持两种策略,默认策略和自定义策略,这个稍后会进行说明。需要注意的是当一个支持缓存的方法在对象内部被调用时是不会触发缓存功能的。

    @Cacheable一般可以指定三个属性,valuekeycondition

    value属性指定Cache名称

    value属性是必须指定的,其表示当前方法的返回值是会被缓存在哪个Cache上的,对应Cache的名称。其可以是一个Cache也可以是多个Cache,当需要指定多个Cache时其是一个数组。

       @Cacheable("cache1")//Cache是发生在cache1上的
    
       public User find(Integer id) {
    
          returnnull;
    
       }
    
    
       @Cacheable({"cache1", "cache2"})//Cache是发生在cache1和cache2上的
    
       public User find(Integer id) {
    
          returnnull;
    
       }
    

    使用key属性自定义key

    key属性是用来指定Spring缓存方法的返回结果时对应的key的。该属性支持SpringEL表达式。当我们没有指定该属性时,Spring将使用默认策略生成key。我们这里先来看看自定义策略,至于默认策略会在后文单独介绍。

    自定义策略是指我们可以通过Spring的EL表达式来指定我们的key。这里的EL表达式可以使用方法参数及它们对应的属性。使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”。下面是几个使用参数作为key的示例。

       @Cacheable(value="users", key="#id")
       public User find(Integer id) {
          return new User(1);
       }
    
       @Cacheable(value="users", key="#p0")
       public User find(Integer id) {
          return new User(1);
       }
    
       @Cacheable(value="users", key="#user.id")
       public User find(User user) {
        return user;
       }
    
    
       @Cacheable(value="users", key="#p0.id")
       public User find(User user) {
          return user;
       }
    

    Condition属性指定发生的条件

    有的时候我们可能并不希望缓存一个方法所有的返回结果。通过condition属性可以实现这一功能。condition属性默认为空,表示将缓存所有的调用情形。其值是通过SpringEL表达式来指定的,当为true时表示进行缓存处理;当为false时表示不进行缓存处理,即每次调用该方法时该方法都会执行一次。如下示例表示只有当user的id为偶数时才会进行缓存。

       @Cacheable(value={"users"}, key="#user.id", condition="#user.id%2==0")
       public User find(User user) {
          System.out.println("find user by user " + user);
          return user;
       }
    

    @CachePut:动态缓存

    在支持Spring Cache的环境下,对于使用@Cacheable标注的方法,Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。@CachePut也可以声明一个方法支持缓存功能。与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。

    @CachePut也可以标注在类上和方法上。使用@CachePut时我们可以指定的属性跟@Cacheable是一样的。

       @CachePut("users")//每次都会执行方法,并将结果存入指定的缓存中
       public User find(Integer id) {
          returnnull;
       }
    

    @CacheEvict:清除缓存

    @CacheEvict 是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作。@CacheEvict可以指定的属性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的语义与@Cacheable对应的属性类似。即value表示清除操作是发生在哪些Cache上的(对应Cache的名称);key表示需要清除的是哪个key,如未指定则会使用默认策略生成的key;condition表示清除操作发生的条件。下面我们来介绍一下新出现的两个属性allEntries和beforeInvocation。

    allEntries属性

    allEntries是boolean类型,表示是否需要清除缓存中的所有元素。默认为false,表示不需要。当指定了allEntries为true时,Spring Cache将忽略指定的key。有的时候我们需要Cache一下清除所有的元素,这比一个一个清除元素更有效率。

       @CacheEvict(value="users", allEntries=true)
       public void delete(Integer id) {
          System.out.println("delete user by id: " + id);
       }
    

    beforeInvocation属性

    清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。

       @CacheEvict(value="users", beforeInvocation=true)
       public void delete(Integer id) {
          System.out.println("delete user by id: " + id);
       }
    

    Ehcache的类层次模型

    Ehcache的类层次模型主要为三层,最上层的是CacheManager,它是操作Ehcache的入口。我们可以通过CacheManager.getInstance()获得一个单个的CacheManager,或者通过CacheManager的构造函数创建一个新的CacheManager.每个CacheManager都管理着多个Cache。而每个Cache都以一种类Hash的方式,关联着多个Element。而Element则是我们用于存放要缓存内容的地方。

    Ehcache的刷新策略

    ehcache的刷新策略是当缓存在放入的时候记录一个放入时间,它是用Lazy Evict的方式,在取的时候同设置的TTL比较 。

    MemoryStore回收策略

    MemoryStore支持三种策略:LRU、LFU、FIFO。

    -LRU:最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清除缓存。

    • LFU:最少被使用,缓存的元素有一个hit属性,hit值最小的将会被清除缓存。

    • FIFO:先进先出。

    EventHandler事件处理

    可以为CacheManager添加事件监听,当对CacheManager增删Cache时,事件处理器将会得到通知。要配置事件处理,需要通过ehcache的配置文件来完成。可以为Cache添加事件监听,当对Cache增删Element时,事件处理器将会得到通知。要配置事件处理,需要通过ehcache的配置文件来完成。

    开源项目spring-cloud-study

    其实应该叫spring-boot-study的,因为很多都是springboot+单个集成。

    我不想集成:直接用EHCACHE API

    如果两个缓存框架集成,或者因为业务需要只能直接用API,则可以参考以下用法。

    Coding with the Ehcache 3 API :

    CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
        .withCache("preConfigured",
             CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
                                            ResourcePoolsBuilder.heap(100))
             .build())
        .build(true);
    
    Cache<Long, String> preConfigured
        = cacheManager.getCache("preConfigured", Long.class, String.class);
    
    Cache<Long, String> myCache = cacheManager.createCache("myCache",
        CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
                                      ResourcePoolsBuilder.heap(100)).build());
    
    myCache.put(1L, "da one!");
    String value = myCache.get(1L);
    
    cacheManager.close();
    
    • 静态方法org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder返回一个新的org.ehcache.config.builders.CacheManagerBuilder实例。
    • 使用构建器来定义别名为“ preConfigured”的缓存。在实际的CacheManager实例上调用cacheManager.build()时,将创建此缓存。第一个String参数是缓存别名,用于从CacheManager检索缓存。第二个参数org.ehcache.config.CacheConfiguration用于配置Cache。我们在org.ehcache.config.builders.CacheConfigurationBuilder上使用静态newCacheConfigurationBuilder()方法来创建默认配置。
    • 最后,调用build()返回我们可以使用的完全实例化但未初始化的CacheManager。
    • 在使用CacheManager之前,需要对其进行初始化,这可以通过2种方式之一进行初始化:在CacheManager实例上调用CacheManager.init(),或者在boolean参数设置为true的情况下调用CacheManagerBuilder.build(boolean init)方法。
    • 通过将其别名,键类型和值类型传递给CacheManager来检索缓存。例如,要获取在步骤2中声明的缓存,您需要使用其别名=“ preConfigured”keyType = Long.classvalueType = String.class。为了确保类型安全,我们要求传递键和值类型。如果这些键和值类型与我们期望的不同,则CacheManager在应用程序生命周期的早期会引发ClassCastException。这可以防止缓存受到随机类型的污染。
    • 可以根据需要使用CacheManager创建新的Cache实例。就像在步骤2中一样,它需要传入别名以及CacheConfiguration。添加的实例化和完全初始化的Cache将通过CacheManager.getCache API返回和/或访问。
    • 现在可以使用新添加的缓存来存储条目,这些条目由键值对组成,跟Map对象一样。 put方法的第一个参数是键,第二个参数是值。请记住,键和值类型必须与CacheConfiguration中定义的类型相同。此外,key必须唯一,并且仅与一个值相关联。
    • 通过调用cache.get(key)方法从缓存中检索值。它仅采用一个参数作为键,并返回与该键关联的值。如果没有与该键关联的值,则返回null。
    • 我们可以CacheManager.removeCache(String)给定的缓存。 CacheManager将不仅删除其对Cache的引用,还将关闭它。缓存释放所有本地保留的瞬时资源(例如内存)。对此缓存的引用将不可用。
    • 为了释放CacheManager提供给它管理的Cache实例的所有瞬时资源(内存,线程等),您必须调用CacheManager.close(),后者依次关闭当时已知的所有Cache实例。

    我还想要监控缓存:cache-event-listeners

    缓存侦听器允许实现者注册将在发生 缓存事件时执行回调方法 。侦听器是在高速缓存级别注册的,因此仅接收已向其注册的高速缓存的事件。

    官方文档也有详细介绍:http://www.ehcache.org/documentation/3.8/cache-event-listeners.html

    CacheEventListenerConfigurationBuilder cacheEventListenerConfiguration = CacheEventListenerConfigurationBuilder
        .newEventListenerConfiguration(new ListenerObject(), EventType.CREATED, EventType.UPDATED) 
        .unordered().asynchronous(); 
    
    final CacheManager manager = CacheManagerBuilder.newCacheManagerBuilder()
        .withCache("foo",
            CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, String.class, ResourcePoolsBuilder.heap(10))
                .withService(cacheEventListenerConfiguration) 
        ).build(true);
    
    final Cache<String, String> cache = manager.getCache("foo", String.class, String.class);
    cache.put("Hello", "World"); 
    cache.put("Hello", "Everyone"); 
    cache.remove("Hello");
    

    Listener 参考,也就是new ListenerObject()的参考实现:

    public class NotNullCacheEventListener implements CacheEventListener {
     
        public static final CacheEventListener INSTANCE = new NotNullCacheEventListener();
     
        @Override
        public void notifyElementRemoved(final Ehcache cache, final Element element) throws CacheException {
        }
     
        @Override
        public void notifyElementPut(final Ehcache cache, final Element element) throws CacheException {
            removeIfNull(cache, element);
        }
     
        @Override
        public void notifyElementUpdated(final Ehcache cache, final Element element) throws CacheException {
            removeIfNull(cache, element);
        }
     
        private void removeIfNull(final Ehcache cache, final Element element) {
            if (element.getObjectValue() == null) {
                cache.remove(element.getKey());
            }
        }
     
        @Override
        public void notifyElementExpired(final Ehcache cache, final Element element) {
        }
     
        @Override
        public void notifyElementEvicted(final Ehcache cache, final Element element) {
        }
     
        @Override
        public void notifyRemoveAll(final Ehcache cache) {
        }
     
        @Override
        public void dispose() {
        }
     
        @Override
        public Object clone() throws CloneNotSupportedException {
            throw new CloneNotSupportedException("Singleton instance");
        }
    }
    
    
    展开全文
  • CPU上下文切换: CPU给每个进程一定的服务时间,当时间片用完后,内核从正在运行的进程中收回处理器,同时把进程当前运行状态保存下来,然后加载下一个任务,这个过程叫做上下文切换。实质上就是被终止运行进程与待...

    缓存机制

    在Linux系统中,为了提高文件系统性能,内核利用一部分物理内存分配出缓冲区,用于缓存系统操作和数据文件,当内核收到读写的请求时,内核先去缓存区找是否有请求的数据,有就直接返回,如果没有则通过驱动程序直接操作磁盘。

    缓存机制优点: 减少系统调用次数,降低CPU上下文切换和磁盘访问频率。

    CPU上下文切换: CPU给每个进程一定的服务时间,当时间片用完后,内核从正在运行的进程中收回处理器,同时把进程当前运行状态保存下来,然后加载下一个任务,这个过程叫做上下文切换。实质上就是被终止运行进程与待运行进程的进程切换。

    Swap用途: Swap意思是交换分区,通常我们说的虚拟内存,是从硬盘中划分出的一个分区。当物理内存不够用的时候,内核就会释放缓存区(buffers/cache)里一些长时间不用的程序,然后将这些程序临时放到Swap中,也就是说如果物理内存和缓存区内存不够用的时候,才会用到Swap。

    swap清理: swapoff -a && swapon -a

    查看缓存区及内存使用情况

    命令输入:free -m //使用-m参数表示以兆字节(MB)为单位显示内存
    在这里插入图片描述


    第一行Mem行解释:
    total:内存总数;
    used:已经使用的内存数;
    free:空闲的内存数;
    shared:当前已经废弃不用;
    buffers Buffer:缓存内存数;
    cached Page:缓存内存数。
    buff/cache: 缓冲区缓存和页面缓存
    关系:total = used + free

    有的第二行 为(-/+ buffers/cache)解释:
    (-buffers/cache) used内存数:第一部分Mem行中的 used – buffers – cached
    (+buffers/cache) free内存数: 第一部分Mem行中的 free + buffers + cached

    可见-buffers/cache反映的是被程序实实在在吃掉的内存,而+buffers/cache反映的是可以挪用的内存总数。

    Swap是指交换分区。

    以字节为单位显示内存
    加上-b参数的free命令,以字节为单位显示内存的大小。
    定期时间间隔更新内存状态
    -s选项加上一个整数,用来在定期时间间隔内更新free命令。
    举个例子,下面的命令将会在每5秒更新一个free命令。
    `free -s 5`
    

    buffers和cached解释

    缓存(cached) 是把读取过的数据保存起来,重新读取时若命中(找到需要的数据)就不要去读硬盘了,若没有命中就读硬盘。其中的数据会根据读取频率进行组织,把最频繁读取的内容放在最容易找到的位置,把不再读的内容不断往后排,直至从中删除。

    缓冲(buffers) 是根据磁盘的读写设计的,把分散的写操作集中进行,减少磁盘碎片和硬盘的反复寻道,从而提高系统性能。linux有一个守护进程定期清空缓冲内容(即写入磁盘),也可以通过sync命令手动清空缓冲。举个例子吧:我这里有一个ext2的U盘,我往里面cp一个3M的MP3,但U盘的灯没有跳动,过了一会儿(或者手动输入sync)U盘的灯就跳动起来了。卸载设备时会清空缓冲,所以有些时候卸载一个设备时要等上几秒钟。

    修改 /etc/sysctl.conf 中的vm.swappiness右边的数字可以在下次开机时调节swap使用策略。该数字范围是0~100,数字越大越倾向于使用swap。默认为60,可以改一下试试。–两者都是RAM中的数据。
    两者都是RAM中的数据,简单来说,buffer是即将要被写入磁盘的,而cache是被从磁盘中读出来的。
    buffer是由各种进程分配的,被用在如输入队列等方面。一个简单的例子如某个进程要求有多个字段读入,在所有字段被读入完整之前,进程把先前读入的字段放在buffer中保存。
    cache经常被用在磁盘的I/O请求上,如果有多个进程都要访问某个文件,于是该文件便被做成cache以方便下次被访问,这样可提高系统性能。

    Cache: 缓冲区,高速缓存,是位于CPU与主内存间的一种容量较小但速度很高的存储器。由于CPU的速度远高于主内存,CPU直接从内存中存取数据要等待一定时间周期,Cache中保存着CPU刚用过或循环使用的一部分数据,当CPU再次使用该部分数据时可从Cache中直接调用,这样就减少了CPU的等待时间,提高了系统的效率。Cache又分为一级Cache(L1 Cache)和二级Cache(L2 Cache),L1 Cache集成在CPU内部,L2 Cache早期一般是焊在主板上,现在也都集成在CPU内部,常见的容量有256KB或512KB L2 Cache。它是根据程序的局部性原理而设计的,就是cpu执行的指令和访问的数据往往在集中的某一块,所以把这块内容放入cache后,cpu就不用在访问内存了,这就提高了访问速度。当然若cache中没有cpu所需要的内容,还是要访问内存的。从内存读取与磁盘读取角度考虑,cache可以理解为操作系统为了更高的读取效率,更多的使用内存来缓存可能被再次访问的数据。

    Cache并不是缓存文件的,而是缓存块的(块是I/O读写最小的单元);Cache一般会用在I/O请求上,如果多个进程要访问某个文件,可以把此文件读入Cache中,这样下一个进程获取CPU控制权并访问此文件直接从Cache读取,提高系统性能。

    Buffer: 缓冲区,一个用于存储速度不同步的设备或优先级不同的设备之间传输数据的区域。通过buffer可以减少进程间通信需要等待的时间,当存储速度快的设备与存储速度慢的设备进行通信时,存储慢的数据先把数据存放到buffer,达到一定程度存储快的设备再读取buffer的数据,在此期间存储快的设备CPU可以干其他的事情。

    Buffer: 一般是用在写入磁盘的,例如:某个进程要求多个字段被读入,当所有要求的字段被读入之前已经读入的字段会先放到buffer中。Buffer是根据磁盘的读写设计的,把分散的写操作集中进行,减少磁盘碎片和硬盘的反复寻道,从而提高系统性能。linux有一个守护进程定期清空缓冲内容(即写入磁盘),也可以通过sync命令手动清空缓冲。

    cache是高速缓存,用于CPU和内存之间的缓冲;
    buffer是I/O缓存,用于内存和硬盘的缓冲;

    cache最初用于cpu cache,主要原因是cpu 与memory,由于cpu快,memory跟不上,且有些值使用次数多,所以放入cache中,主要目的是,重复使用,并且一级\二级物理cache速度快,
    buffer主要用于disk与 memory,主要是保护硬盘或减少网络传输的次数(内存数据表现dataSet).当然也可以提高速度(不会立即写入硬盘或直接从硬盘中读出的数据马上显示),重复使用,最初最主要的目的是保护disk,

    Free中的buffer和cache:(它们都是占用内存):
    buffer : 作为buffer cache的内存,是块设备的读写缓冲区
    cache: 作为page cache的内存, 文件系统的cache

    如果 cache 的值很大,说明cache住的文件数很多。如果频繁访问到的文件都能被cache住,那么磁盘的读IO bi会非常小。

    简单通俗的例子来说明下Cache和Buffer缓存之间的区别:

    1)Cache缓存

    假设某地发生了自然灾害(比如地震),居民缺衣少食,于是派救火车去给若干个居民点送水。救火车到达第一个居民点,开闸放水,老百姓就拿着盆盆罐罐来接水。假如说救火车在一个居民点停留100分钟放完了水,然后重新储水花半个小时,再开往下一个居民点。这样一个白天来来来回回的,也就是4-5个居民点。

    但我们想想,救火车是何等存在,如果把水龙头完全打开,其强大的水压能轻易冲上10层楼以上, 10分钟就可以把水全部放完。但因为居民是拿盆罐接水,100%打开水龙头那就是给人洗澡了,所以只能打开一小部分(比如10%的流量)。但这样就降低了放水的效率(只有原来的10%了),10分钟变100分钟。

    那么,我们是否能改进这个放水的过程,让救火车以最高效率放完水、尽快赶往下一个居民点呢?
    方法就是:在居民点建蓄水池。
    救火车把水放到蓄水池里,因为是以100%的效率放水,10分钟结束然后走人。居民再从蓄水池里一点一点的接水。

    我们分析一下这个例子,就可以知道Cache的含义了。
    救火车要给居民送水,居民要从救火车接水,就是说居民和救火车之间有交互,有联系。
    但救火车是"高速设备",居民是"低速设备",低速的居民跟不上高速的救火车,所以救火车被迫降低了放水速度以适应居民。
    为了避免这种情况,在救火车和居民之间多了一层"蓄水池(也就是Cache)",它一方面以100%的高效和救火车打交道,另一方面以10%的低效和居民打交道,这就解放了救火车,让其以最高的效率运行,而不被低速的居民拖后腿,于是救火车只需要在一个居民点停留10分钟就可以了。
    所以说,蓄水池是"活雷锋",把高效留给别人,把低效留给自己。把10分钟留给救火车,把100分钟留给自己。

    从以上例子可以看出,所谓Cache,就是"为了弥补高速设备和低速设备之间的矛盾"而设立的一个中间层。因为在现实里经常出现高速设备要和低速设备打交道,结果被低速设备拖后腿的情况。Cache的存在是为了解决什么问题?速度太慢了,要加快速度!

    以PC为例。CPU速度很快,但CPU执行的指令是从内存取出的,计算的结果也要写回内存,但内存的响应速度跟不上CPU。CPU跟内存说:你把某某地址的指令发给我。内存听到了,但因为速度慢,迟迟不见指令返回,这段时间,CPU只能无所事事的等待了。这样一来,再快的CPU也发挥不了效率。
    怎么办呢?在CPU和内存之间加一块"蓄水池",也就是Cache(片上缓存),这个Cache速度比内存快,从Cache取指令不需要等待。当CPU要读内存的指令的时候先读Cache再读内存,但一开始Cache是空着的,只能从内存取,这时候的确是很慢,CPU需要等待。但从内存取回的不仅仅是CPU所需要的指令,还有其它的、当前不需要的指令,然后把这些指令存在Cache里备用。CPU再取指令的时候还是先读Cache,看看里面有没有所需指令,如果碰巧有就直接从Cache取,不用等待即可返回(命中),这就解放了CPU,提高了效率。(当然不会是100%命中,因为Cache的容量比内存小)

    2)Buffer缓存

    比如说吐鲁番的葡萄熟了,要用大卡车装葡萄运出去卖果园的姑娘采摘葡萄,当然不是前手把葡萄摘下来,后手就放到卡车上,而是需要一个中间过程"箩筐":摘葡萄→放到箩筐里→把箩筐里的葡萄倒入卡车。也就是说,虽然最终目的是"把葡萄倒入卡车",但中间必须要经过"箩筐"的转手,这里的箩筐就是Buffer。是"暂时存放物品的空间"。
    注意2个关键词:暂时,空间
    再换句话说,为了完成最终目标:把葡萄放入卡车的空间,需要暂时把葡萄放入箩筐的空间。

    以BT为例,BT下载需要长时间的挂机,电脑就有可能24小时连轴转,但BT下载的数据是碎片化的,体现在硬盘写入上也是碎片化的,因为硬盘是机械寻址器件,这种碎片化的写入会造成硬盘长时间高负荷的机械运动,造成硬盘过早老化损坏,当年有大量的硬盘因为BT下载而损坏。于是新出的BT软件在内存里开辟了Buffer,数据暂时写入Buffer,攒到一定的大小(比如512M)再一次性写入硬盘,这种"化零为整"的写入方式大大降低了硬盘的负荷。这就是:为了完成最终目标:把数据写入硬盘空间,需要暂时写入Buffer的空间。

    3)二者之间的区别总结

    Cache和Buffer的相同点:都是2个层面之间的中间层,都是内存。
    Cache和Buffer的不同点:Cache解决的是时间问题,Buffer解决的是空间问题。
    为了提高速度,引入了Cache这个中间层。
    为了给信息找到一个暂存空间,引入了Buffer这个中间层。
    为了解决2个不同维度的问题(时间、空间),恰巧取了同一种解决方法:加入一个中间层,先把数据写到中间层上,然后再写入目标。
    这个中间层就是内存“RAM”,既然是存储器就有2个参数:写入的速度有多块(速度),能装多少东西(容量)
    Cache利用的是RAM提供的高读写速度,Buffer利用的是RAM提供的存储容量(空间)。

    a)Buffer(缓冲区)是系统两端处理速度平衡(从长时间尺度上看)时使用的。它的引入是为了减小短期内突发I/O的影响,起到流量整形的作用。比如生产者——消费者问题,他们产生和消耗资源的速度大体接近,加一个buffer可以抵消掉资源刚产生/消耗时的突然变化。
    b)Cache(缓存)则是系统两端处理速度不匹配时的一种折衷策略。因为CPU和memory之间的速度差异越来越大,所以人们充分利用数据的局部性(locality)特征,通过使用存储系统分级(memory hierarchy)的策略来减小这种差异带来的影响。
    c)假定以后存储器访问变得跟CPU做计算一样快,cache就可以消失,但是buffer依然存在。比如从网络上下载东西,瞬时速率可能会有较大变化,但从长期来看却是稳定的,这样就能通过引入一个buffer使得OS接收数据的速率更稳定,进一步减少对磁盘的伤害。

    缓存优化方法

    释放缓存区内存的方法

    1)清理pagecache(页面缓存)
    echo 1 > /proc/sys/vm/drop_cachessysctl -w vm.drop_caches=1
    [root@ackh-office-srv ~]# echo 1 > /proc/sys/vm/drop_caches 或者 # sysctl -w vm.drop_caches=1

    2)清理dentries(目录缓存)和inodes
    echo 2 > /proc/sys/vm/drop_cachessysctl -w vm.drop_caches=2
    [root@ackh-office-srv ~]# echo 2 > /proc/sys/vm/drop_caches 或者 # sysctl -w vm.drop_caches=2

    3)清理pagecache、dentries和inodes
    echo 3 > /proc/sys/vm/drop_cachessysctl -w vm.drop_caches=3
    [root@ackh-office-srv ~]# echo 3 > /proc/sys/vm/drop_caches 或者 # sysctl -w vm.drop_caches=3

    注意

    上面三种方式都是临时释放缓存的方法,要想永久释放缓存,
    需要在
    vim /etc/sysctl.conf
    添加配置vm.drop_caches=1/2/3

    sysctl -p

    /etc/sysctl.conf文件中配置:vm.drop_caches=1/2/3,然后sysctl -p生效即可!

    另外,可以使用sync命令来清理文件系统缓存,还会清理僵尸(zombie)对象和它们占用的内存
    sync
    [root@ackh-office-srv ~]# sync

    温馨提示:

    上面操作在大多数情况下都不会对系统造成伤害,只会有助于释放不用的内存。
    但是如果在执行这些操作时正在写数据,那么实际上在数据到达磁盘之前就将它从文件缓存中清除掉了,这可能会造成很不好的影响。

    那么如果避免这种事情发生呢?

    因此,这里不得不提一下/proc/sys/vm/vfs_cache_pressure这个文件,告诉内核,当清理inoe/dentry缓存时应该用什么样的优先级。
    cat /proc/sys/vm/vfs_cache_pressure
    [root@ackh-office-srv ~]# cat /proc/sys/vm/vfs_cache_pressure
    100

    vfs_cache_pressure=100 这个是默认值,内核会尝试重新声明dentries和inodes,并采用一种相对于页面缓存和交换缓存比较"合理"的比例。

    减少vfs_cache_pressure的值,会导致内核倾向于保留dentry和inode缓存。
    增加vfs_cache_pressure的值,(即超过100时),则会导致内核倾向于重新声明dentries和inodes

    总之,vfs_cache_pressure的值:
    小于100的值不会导致缓存的大量减少
    超过100的值则会告诉内核你希望以高优先级来清理缓存。

    其实无论vfs_cache_pressure的值采用什么值,内核清理缓存的速度都是比较低的。

    如果将此值设置为10000,系统将会将缓存减少到一个

    合理的水平。 YES!

    展开全文
  • mybaits提供一级缓存二级缓存。 一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个(内存区域)数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据...
  • 服务器上进程运行查看方式

    千次阅读 2019-06-20 21:48:35
    Linux 服务器正常启动后,提供服务时会调用程序,占用进程。这时候我们如何查看系统中有哪些进程在被调用呢?我们可以通过以下命令来查看。 一、ps 命令 ps 命令是最基本同时也是非常强大的进程查看命令。使用...
  • 我之前写过一篇博客,介绍缓存处理的三种方式,其中最难,最麻烦,最占内存资源的还是图片缓存,最近做的项目有大量的图片处理,还是采用了SDWebImage来处理,但是发现之前封装好的代码报错了。研究发现,是我用了...
  • Hibernate缓存机制MyBatis缓存机制

    万次阅读 2016-09-29 09:42:04
    原文地址:... 摘要: mybatis缓存分为1级缓存和2级缓存 mybatis缓存分为1级缓存和2级缓存,2级缓存在sessionfactory中,1级缓存在session中。 session中的缓存在session连接关闭并被连接池回收时
  • top命令可以实时动态地查看系统的整体运行情况,是一个综合了多方信息监测系统性能和运行信息的实用工具。通过top命令所提供的互动式界面,用热键可以管理。语法top(选项)选项-b:以批处理模式操作; -c:显示完整的...
  • Caffeine 缓存

    万次阅读 2017-12-13 17:07:05
    缓存和 Map 之间的一个根本区别在于缓存可以回收存储的 item。 回收策略为在指定时间删除哪些对象。此策略直接影响缓存的命中率 — 缓存库的一个重要特征。 Caffeine 因使用 Window TinyLfu 回收策略,提供了一个...
  • 静态文件缓存在单个服务器执行时运行良好,但其实硬件方面依然由 web 服务器应用程序服务器共享。如果 web 服务器使用硬件找回缓存的文件(及时非常高效)应用程序将无法使用这些硬件,运行速度可能会受到影响。 ...
  • 缓存是介于应用程序物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或...
  • ArcGIS Server 10:发布缓存的地图服务

    千次阅读 2013-01-10 10:56:45
    对地图服务进行缓存时,服务器会以您定义保存图像的一组比例级别来绘制地图。当服务器接收到对地图的请求时,与重新绘制地图相比,返回已缓存图像中的地图会更加快捷。 缓存适用于不经常更改的底图地图。对于...
  • Hibernate缓存和ehcache

    千次阅读 2012-11-22 22:04:32
    它介于应用程序永久性数据存储源(如硬盘上的文件或者数据库)之间,其作用是降低应用程序直接读写永久性数据存储源的频率,从而提高应用的运行性能。缓存中的数据是存储源总的数据的拷贝。缓存的物理介质通常是...
  • 缓存服务器Cache Server 6.0发布

    千次阅读 2018-12-11 16:43:48
    无论是在个人的本地电脑,还是在团队的局域网专有服务器上,缓存服务器都能通过优化资源导入过程让使用Unity开发的速度变得更快。远程缓存服务器Cache Server 6.0版本现已发布,缓存服务器的质量性能获得大幅提高...
  • Discuz! 的主动缓存和被动缓存

    千次阅读 2009-07-16 16:52:00
    缓存同样分了主动缓存和被动缓存。本文详细讲述两种缓存的异同!Discuz!的缓存同样分了主动缓存和被动缓存。从功能上来说,主动缓存一般用到管理员对全站的设置,等等需要手动更新的地方,这些地方的数据都有一个...
  • 微博缓存服务化的设计与实践

    千次阅读 2016-09-03 13:59:33
    导读:高可用架构 8 月...09 年之后从事新浪微博的系统研发及架构工作,在海量数据存储、峰值访问、规模化缓存服务及开放平台等方面参与技术架构改进,当前主要负责微博平台的基础设施、中间件的研发及架构优化工作,经
  • 缓存Memcached以及缓存策略

    万次阅读 2014-05-14 09:56:17
    缓存是我们在设计中考虑的如何提高软件性能的方法,使用memcached这款简单的K/V缓存,提升软件性能,降低服务器压力。
  • 概述Velocity是微软推出的分布式缓存解决方案,为开发可扩展性,可用的,高性能的应用程提供支持,可以缓存各种类型的数据,如CLR对象、XML、二进制数据等,并且支持集群模式的缓存服务器。Velocity也将集成在.NET ...
  • hibernate 缓存

    千次阅读 2016-04-11 11:13:02
    简介缓存 缓存是广泛使用的用于优化数据库应用程序。缓存的目的是减少你的应用程序,并通过保存从数据库已加载数据的数据库之间的流量。...Hibernate使用的对象两个不同的缓存:一级缓存和二级缓存。第
  • 磁盘缓存、Hibernate缓存、Mybatis缓存

    千次阅读 2017-03-12 21:47:10
    一、磁盘缓存:(disk cache)磁盘缓存分为读缓存和缓存。 (1)读缓存指的是把从磁盘中读取的数据存储到内存空间中的方式。这样一来,当接下来需要读取同一数据时,就不用查询实际的磁盘,而是从磁盘缓存(内存)...
  • 1,比如在软件运行过程中,获取当前的角色,修改信息,改变位置。 2.在脚本中获得数据后,如何发送给程序接受?
  • 缓存是介于应用程序物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或...
  • 缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。  缓存的介质一般是内存,所以读写速度很快。但如果缓存中存放的数据量非常大...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 412,530
精华内容 165,012
关键字:

当前运行的服务和缓存的进程