Redis整合Spring结合使用缓存实例

  林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka

         摘要:本文介绍了如何在Spring中配置redis,并通过Spring中AOP的思想,将缓存的方法切入到有需要进入缓存的类或方法前面。

一、Redis介绍

什么是Redis?

      redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

它有什么特点?

(1)Redis数据库完全在内存中,使用磁盘仅用于持久性。
(2)相比许多键值数据存储,Redis拥有一套较为丰富的数据类型。
(3)Redis可以将数据复制到任意数量的从服务器。

Redis 优势?
 (1)异常快速:Redis的速度非常快,每秒能执行约11万集合,每秒约81000+条记录。
 (2)支持丰富的数据类型:Redis支持最大多数开发人员已经知道像列表,集合,有序集合,散列数据类型。这使得它非常容易解决各种各样的问题,因为我们知道哪些问题是可以处理通过它的数据类型更好。
(3)操作都是原子性:所有Redis操作是原子的,这保证了如果两个客户端同时访问的Redis服务器将获得更新后的值。
(4)多功能实用工具:Redis是一个多实用的工具,可以在多个用例如缓存,消息,队列使用(Redis原生支持发布/订阅),任何短暂的数据,应用程序,如Web应用程序会话,网页命中计数等。

Redis 缺点?

(1)单线程

(2)耗内存

二、使用实例

本文使用maven+eclipse+sping

1、引入jar包

 

[html] view plaincopy
  1.     <!--Redis start -->  
  2. <dependency>  
  3.     <groupId>org.springframework.data</groupId>  
  4.     <artifactId>spring-data-redis</artifactId>  
  5.     <version>1.6.1.RELEASE</version>  
  6. </dependency>  
  7. <dependency>  
  8.     <groupId>redis.clients</groupId>  
  9.     <artifactId>jedis</artifactId>  
  10.     <version>2.7.3</version>  
  11. </dependency>  
  12.    <!--Redis end -->  


2、配置bean

 

在application.xml加入如下配置

 

[html] view plaincopy
  1. <!-- jedis 配置 -->  
  2.    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig" >  
  3.          <property name="maxIdle" value="${redis.maxIdle}" />  
  4.          <property name="maxWaitMillis" value="${redis.maxWait}" />  
  5.          <property name="testOnBorrow" value="${redis.testOnBorrow}" />  
  6.    </bean >  
  7.   <!-- redis服务器中心 -->  
  8.    <bean id="connectionFactory"  class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >  
  9.          <property name="poolConfig" ref="poolConfig" />  
  10.          <property name="port" value="${redis.port}" />  
  11.          <property name="hostName" value="${redis.host}" />  
  12.          <property name="password" value="${redis.password}" />  
  13.          <property name="timeout" value="${redis.timeout}" ></property>  
  14.    </bean >  
  15.    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" >  
  16.          <property name="connectionFactory" ref="connectionFactory" />  
  17.          <property name="keySerializer" >  
  18.              <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />  
  19.          </property>  
  20.          <property name="valueSerializer" >  
  21.              <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />  
  22.          </property>  
  23.    </bean >  
  24.      
  25.     <!-- cache配置 -->  
  26.    <bean id="methodCacheInterceptor" class="com.mucfc.msm.common.MethodCacheInterceptor" >  
  27.          <property name="redisUtil" ref="redisUtil" />  
  28.    </bean >  
  29.    <bean id="redisUtil" class="com.mucfc.msm.common.RedisUtil" >  
  30.          <property name="redisTemplate" ref="redisTemplate" />  
  31.    </bean >  


其中配置文件redis一些配置数据redis.properties如下:

 

 

[plain] view plaincopy
  1. #redis中心  
  2. redis.host=10.75.202.11  
  3. redis.port=6379  
  4. redis.password=123456  
  5. redis.maxIdle=100  
  6. redis.maxActive=300  
  7. redis.maxWait=1000  
  8. redis.testOnBorrow=true  
  9. redis.timeout=100000  
  10.   
  11. # 不需要加入缓存的类  
  12. targetNames=xxxRecordManager,xxxSetRecordManager,xxxStatisticsIdentificationManager  
  13. # 不需要缓存的方法  
  14. methodNames=  
  15.   
  16. #设置缓存失效时间  
  17. com.service.impl.xxxRecordManager= 60  
  18. com.service.impl.xxxSetRecordManager= 60  
  19. defaultCacheExpireTime=3600  
  20.   
  21. fep.local.cache.capacity =10000  


要扫这些properties文件,在application.xml加入如下配置

 

 

[plain] view plaincopy
  1.  <!-- 引入properties配置文件 -->    
  2.  <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  3.     <property name="locations">  
  4.         <list>  
  5.            <value>classpath:properties/*.properties</value>  
  6.             <!--要是有多个配置文件,只需在这里继续添加即可 -->  
  7.         </list>  
  8.     </property>  
  9. </bean>  

3、一些工具类

(1)RedisUtil

上面的bean中,RedisUtil是用来缓存和去除数据的实例

 

[java] view plaincopy
  1. package com.mucfc.msm.common;  
  2.   
  3. import java.io.Serializable;  
  4. import java.util.Set;  
  5. import java.util.concurrent.TimeUnit;  
  6.   
  7. import org.apache.log4j.Logger;  
  8. import org.springframework.data.redis.core.RedisTemplate;  
  9. import org.springframework.data.redis.core.ValueOperations;  
  10.   
  11. /** 
  12.  * redis cache 工具类 
  13.  *  
  14.  */  
  15. public final class RedisUtil {  
  16.     private Logger logger = Logger.getLogger(RedisUtil.class);  
  17.     private RedisTemplate<Serializable, Object> redisTemplate;  
  18.   
  19.     /** 
  20.      * 批量删除对应的value 
  21.      *  
  22.      * @param keys 
  23.      */  
  24.     public void remove(final String... keys) {  
  25.         for (String key : keys) {  
  26.             remove(key);  
  27.         }  
  28.     }  
  29.   
  30.     /** 
  31.      * 批量删除key 
  32.      *  
  33.      * @param pattern 
  34.      */  
  35.     public void removePattern(final String pattern) {  
  36.         Set<Serializable> keys = redisTemplate.keys(pattern);  
  37.         if (keys.size() > 0)  
  38.             redisTemplate.delete(keys);  
  39.     }  
  40.   
  41.     /** 
  42.      * 删除对应的value 
  43.      *  
  44.      * @param key 
  45.      */  
  46.     public void remove(final String key) {  
  47.         if (exists(key)) {  
  48.             redisTemplate.delete(key);  
  49.         }  
  50.     }  
  51.   
  52.     /** 
  53.      * 判断缓存中是否有对应的value 
  54.      *  
  55.      * @param key 
  56.      * @return 
  57.      */  
  58.     public boolean exists(final String key) {  
  59.         return redisTemplate.hasKey(key);  
  60.     }  
  61.   
  62.     /** 
  63.      * 读取缓存 
  64.      *  
  65.      * @param key 
  66.      * @return 
  67.      */  
  68.     public Object get(final String key) {  
  69.         Object result = null;  
  70.         ValueOperations<Serializable, Object> operations = redisTemplate  
  71.                 .opsForValue();  
  72.         result = operations.get(key);  
  73.         return result;  
  74.     }  
  75.   
  76.     /** 
  77.      * 写入缓存 
  78.      *  
  79.      * @param key 
  80.      * @param value 
  81.      * @return 
  82.      */  
  83.     public boolean set(final String key, Object value) {  
  84.         boolean result = false;  
  85.         try {  
  86.             ValueOperations<Serializable, Object> operations = redisTemplate  
  87.                     .opsForValue();  
  88.             operations.set(key, value);  
  89.             result = true;  
  90.         } catch (Exception e) {  
  91.             e.printStackTrace();  
  92.         }  
  93.         return result;  
  94.     }  
  95.   
  96.     /** 
  97.      * 写入缓存 
  98.      *  
  99.      * @param key 
  100.      * @param value 
  101.      * @return 
  102.      */  
  103.     public boolean set(final String key, Object value, Long expireTime) {  
  104.         boolean result = false;  
  105.         try {  
  106.             ValueOperations<Serializable, Object> operations = redisTemplate  
  107.                     .opsForValue();  
  108.             operations.set(key, value);  
  109.             redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);  
  110.             result = true;  
  111.         } catch (Exception e) {  
  112.             e.printStackTrace();  
  113.         }  
  114.         return result;  
  115.     }  
  116.   
  117.     public void setRedisTemplate(  
  118.             RedisTemplate<Serializable, Object> redisTemplate) {  
  119.         this.redisTemplate = redisTemplate;  
  120.     }  
  121. }  

(2)MethodCacheInterceptor

 

切面MethodCacheInterceptor,这是用来给不同的方法来加入判断如果缓存存在数据,从缓存取数据。否则第一次从数据库取,并将结果保存到缓存 中去。

 

[java] view plaincopy
  1. package com.mucfc.msm.common;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.InputStream;  
  6. import java.util.ArrayList;  
  7. import java.util.List;  
  8. import java.util.Properties;  
  9.   
  10. import org.aopalliance.intercept.MethodInterceptor;  
  11. import org.aopalliance.intercept.MethodInvocation;  
  12. import org.apache.log4j.Logger;  
  13.   
  14.   
  15. public class MethodCacheInterceptor implements MethodInterceptor {  
  16.     private Logger logger = Logger.getLogger(MethodCacheInterceptor.class);  
  17.     private RedisUtil redisUtil;  
  18.     private List<String> targetNamesList; // 不加入缓存的service名称  
  19.     private List<String> methodNamesList; // 不加入缓存的方法名称  
  20.     private Long defaultCacheExpireTime; // 缓存默认的过期时间  
  21.     private Long xxxRecordManagerTime; //  
  22.     private Long xxxSetRecordManagerTime; //  
  23.   
  24.     /** 
  25.      * 初始化读取不需要加入缓存的类名和方法名称 
  26.      */  
  27.     public MethodCacheInterceptor() {  
  28.         try {  
  29.              File f = new File("D:\\lunaJee-workspace\\msm\\msm_core\\src\\main\\java\\com\\mucfc\\msm\\common\\cacheConf.properties");   
  30.              //配置文件位置直接被写死,有需要自己修改下  
  31.              InputStream in = new FileInputStream(f);   
  32. //          InputStream in = getClass().getClassLoader().getResourceAsStream(  
  33. //                  "D:\\lunaJee-workspace\\msm\\msm_core\\src\\main\\java\\com\\mucfc\\msm\\common\\cacheConf.properties");  
  34.             Properties p = new Properties();  
  35.             p.load(in);  
  36.             // 分割字符串  
  37.             String[] targetNames = p.getProperty("targetNames").split(",");  
  38.             String[] methodNames = p.getProperty("methodNames").split(",");  
  39.   
  40.             // 加载过期时间设置  
  41.             defaultCacheExpireTime = Long.valueOf(p.getProperty("defaultCacheExpireTime"));  
  42.             xxxRecordManagerTime = Long.valueOf(p.getProperty("com.service.impl.xxxRecordManager"));  
  43.             xxxSetRecordManagerTime = Long.valueOf(p.getProperty("com.service.impl.xxxSetRecordManager"));  
  44.             // 创建list  
  45.             targetNamesList = new ArrayList<String>(targetNames.length);  
  46.             methodNamesList = new ArrayList<String>(methodNames.length);  
  47.             Integer maxLen = targetNames.length > methodNames.length ? targetNames.length  
  48.                     : methodNames.length;  
  49.             // 将不需要缓存的类名和方法名添加到list中  
  50.             for (int i = 0; i < maxLen; i++) {  
  51.                 if (i < targetNames.length) {  
  52.                     targetNamesList.add(targetNames[i]);  
  53.                 }  
  54.                 if (i < methodNames.length) {  
  55.                     methodNamesList.add(methodNames[i]);  
  56.                 }  
  57.             }  
  58.         } catch (Exception e) {  
  59.             e.printStackTrace();  
  60.         }  
  61.     }  
  62.   
  63.     @Override  
  64.     public Object invoke(MethodInvocation invocation) throws Throwable {  
  65.         Object value = null;  
  66.   
  67.         String targetName = invocation.getThis().getClass().getName();  
  68.         String methodName = invocation.getMethod().getName();  
  69.         // 不需要缓存的内容  
  70.         //if (!isAddCache(StringUtil.subStrForLastDot(targetName), methodName)) {  
  71.         if (!isAddCache(targetName, methodName)) {  
  72.             // 执行方法返回结果  
  73.             return invocation.proceed();  
  74.         }  
  75.         Object[] arguments = invocation.getArguments();  
  76.         String key = getCacheKey(targetName, methodName, arguments);  
  77.         System.out.println(key);  
  78.   
  79.         try {  
  80.             // 判断是否有缓存  
  81.             if (redisUtil.exists(key)) {  
  82.                 return redisUtil.get(key);  
  83.             }  
  84.             // 写入缓存  
  85.             value = invocation.proceed();  
  86.             if (value != null) {  
  87.                 final String tkey = key;  
  88.                 final Object tvalue = value;  
  89.                 new Thread(new Runnable() {  
  90.                     @Override  
  91.                     public void run() {  
  92.                         if (tkey.startsWith("com.service.impl.xxxRecordManager")) {  
  93.                             redisUtil.set(tkey, tvalue, xxxRecordManagerTime);  
  94.                         } else if (tkey.startsWith("com.service.impl.xxxSetRecordManager")) {  
  95.                             redisUtil.set(tkey, tvalue, xxxSetRecordManagerTime);  
  96.                         } else {  
  97.                             redisUtil.set(tkey, tvalue, defaultCacheExpireTime);  
  98.                         }  
  99.                     }  
  100.                 }).start();  
  101.             }  
  102.         } catch (Exception e) {  
  103.             e.printStackTrace();  
  104.             if (value == null) {  
  105.                 return invocation.proceed();  
  106.             }  
  107.         }  
  108.         return value;  
  109.     }  
  110.   
  111.     /** 
  112.      * 是否加入缓存 
  113.      *  
  114.      * @return 
  115.      */  
  116.     private boolean isAddCache(String targetName, String methodName) {  
  117.         boolean flag = true;  
  118.         if (targetNamesList.contains(targetName)  
  119.                 || methodNamesList.contains(methodName)) {  
  120.             flag = false;  
  121.         }  
  122.         return flag;  
  123.     }  
  124.   
  125.     /** 
  126.      * 创建缓存key 
  127.      * 
  128.      * @param targetName 
  129.      * @param methodName 
  130.      * @param arguments 
  131.      */  
  132.     private String getCacheKey(String targetName, String methodName,  
  133.             Object[] arguments) {  
  134.         StringBuffer sbu = new StringBuffer();  
  135.         sbu.append(targetName).append("_").append(methodName);  
  136.         if ((arguments != null) && (arguments.length != 0)) {  
  137.             for (int i = 0; i < arguments.length; i++) {  
  138.                 sbu.append("_").append(arguments[i]);  
  139.             }  
  140.         }  
  141.         return sbu.toString();  
  142.     }  
  143.   
  144.     public void setRedisUtil(RedisUtil redisUtil) {  
  145.         this.redisUtil = redisUtil;  
  146.     }  
  147. }  


4、配置需要缓存的类或方法

 

在application.xml加入如下配置,有多个类或方法可以配置多个

 

[html] view plaincopy
  1. <!-- 需要加入缓存的类或方法 -->  
  2. <bean id="methodCachePointCut"  class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" >  
  3.       <property name="advice" >  
  4.           <ref local="methodCacheInterceptor" />  
  5.       </property>  
  6.       <property name="patterns" >  
  7.           <list>  
  8.            <!-- 确定正则表达式列表 -->  
  9.              <value>com\.mucfc\.msm\.service\.impl\...*ServiceImpl.*</value >  
  10.           </list>  
  11.       </property>  
  12. </bean >  


5、执行结果:

 

写了一个简单的单元测试如下:

 

[java] view plaincopy
  1. @Test  
  2. public void getSettUnitBySettUnitIdTest() {  
  3.     String systemId = "CES";  
  4.     String merchantId = "133";  
  5.     SettUnit configSettUnit = settUnitService.getSettUnitBySettUnitId(systemId, merchantId, "ESP");  
  6.     SettUnit configSettUnit1 = settUnitService.getSettUnitBySettUnitId(systemId, merchantId, "ESP");  
  7.     boolean flag= (configSettUnit == configSettUnit1);  
  8.     System.out.println(configSettUnit);  
  9.     logger.info("查找结果" + configSettUnit.getBusinessType());  
  10.     
  11.   //  localSecondFIFOCache.put("configSettUnit", configSettUnit.getBusinessType());  
  12.  //  String string = localSecondFIFOCache.get("configSettUnit");  
  13.       logger.info("查找结果" + string);  
  14. }  

这是第一次执行单元测试的过程:

 

MethodCacheInterceptor这个类中打了断点,然后每次查询前都会先进入这个方法

 

 

 

依次运行,发现没有缓存,所以会直接去查数据库

打印了出来的SQL语句:

第二次执行:

因为第一次执行时,已经写入缓存了。所以第二次直接从缓存中取数据

3、取两次的结果进行地址的对比:

发现两个不是同一个对象,没错,是对的。如果是使用ehcache的话,那么二者的内存地址会是一样的。那是因为redis和ehcache使用的缓存机制是不一样的。ehcache是基于本地电脑的内存使用缓存,所以使用缓存取数据时直接在本地电脑上取。转换成java对象就会是同一个内存地址,而redis它是在装有redis服务的电脑上(一般是另一台电脑),所以取数据时经过传输到本地,会对应到不同的内存地址,所以用==来比较会返回false。但是它确实是从缓存中去取的,这点我们从上面的断点可以看到。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/293216.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

读取无线手柄数据_xbox series x/s 手柄开箱

原标题&#xff1a;xbox series x/s 手柄开箱xbox series x/s 手柄开箱 2020-11-12 08:29:003点赞2收藏4评论小编注&#xff1a;此篇文章来自#原创新人#激励计划&#xff0c;新人发文前三篇文章&#xff0c;篇篇额外奖励50金币。参加超级新人计划活动&#xff0c;新人发文即可瓜…

豆瓣评分9.4!这一部纪录片,探秘中国人迹罕至的未至之境!

全世界只有3.14 % 的人关注了爆炸吧知识Bilibili 联合“美国国家地理”&#xff0c;悄悄出品了一部史诗级动物记录片&#xff0c;忍不住要推荐给大朋友小朋友们——《未至之境》。这部纪录片由B站和国家地理联合创作&#xff0c;从绵延万里的山脉高原到枝繁叶茂的雨林竹海&…

使用OpenTelemetry搭配Zipkin构建NetCore分布式链路跟踪 | WebAPI + gRPC

OpenTelemetry介绍OpenTelemetry是一组标准和工具的集合&#xff0c;旨在管理观测类数据&#xff0c;如 trace、metrics、logs 等。通过标准化不同的应用程序和框架如何收集和发出可观察性遥测数据&#xff0c;OpenTelemetry旨在解决这些环境带来的一些挑战。OpenTelemetry包括…

腾讯云cloudlite认证_【腾讯云】考个证...大数据开发工程师认证

作为一个大数据行业的从业者&#xff0c;考个腾讯云大数据开发工程师认证总比考个消防证 easy 吧…&#xff1f;关于考这个认证的意义其实主要在于全面复习一下大数据相关的知识点&#xff0c;另外有个腾讯云的认证&#xff0c;也许大概也会对你找工作有点帮助的吧&#xff1f;…

kernel shell bash简介

还记得我们在Linux启动的时候。首先会启动内核 (kernel)&#xff0c;内核是一段计算机程序&#xff0c;这个程序直接管理管理硬件&#xff0c;包括CPU、内存空间、硬盘接口、网络接口等等。所有的计算机操作都要通过内核传递给硬件。为了我们方便调用内核&#xff0c;我们将内核…

最高调恋爱方式,简直“公开处刑”......

1 我拿到了剑桥的offer...▼2 当空乘专业第一次穿高跟鞋...▼3 是我没错了▼4 笑出鹅叫▼5 现场表演一下&#xff0c;一秒落汤鸡&#xff01;▼6 那个红/黄毛起来一下&#xff01;▼7 最高调的恋爱方式▼7 数学可以多好玩▼你点的每个赞&#xff0c;我都认真当成了喜欢

C# 扩展集合ObservableCollection使集合在添加、删除、值变更后触发事件

01—概述ObservableCollection继承了INotifyPropertyChanged接口&#xff0c;在属性变更时可以通知界面&#xff0c;当我把ObservableCollection集合绑定到界面的DataGrid后&#xff0c;我希望在界面修改表格数值后&#xff0c;可以触发一个 事件来验证我界面设定数据的有效性&…

数据挖掘算法之决策树算法总结

机器学习中&#xff0c;决策树是一个预测模型&#xff1b;它代表的是对象属性值与对象值之间的一种映射关系。树中每个节点表示某个对象&#xff0c;每个分叉路径则代表的某个可能的属性值&#xff0c;而每个叶结点则对应具有上述属性值的子对象。决策树仅有单一输出&#xff1…

win7升级win10正式版_win7告退在即,如何升级到win10?

Win7即将停更&#xff0c;小伙伴们也差不多要进行自己系统的更新啦&#xff0c;今天小白就教大家如何将Win7升级到Win10第一步&#xff1a;首先在官网 www.xiaobaixitong.com 下载“小白软件”第二步&#xff1a;选好我们要下载的系统&#xff0c;然后安装即可。第三步&#xf…

在24小时内学完所有的数学是种什么体验?我们做了这个大胆的尝试……

全世界只有3.14 % 的人关注了爆炸吧知识人还好就是没了而已其实&#xff0c;在此时&#xff0c;还有一件事情发生了。22:00&#xff0c;我们发出了这篇文章&#xff0c;不仅将2600多年的数学简史浓缩成24小时&#xff0c;还将2600多年数学简史浓缩成54张卡牌。每张卡牌背后都有…

Server Develop (八) IOCP模型

IOCP模型 IOCP全称I/O Completion Port&#xff0c;中文译为I/O完成端口。IOCP是一个异步I/O的Windows API&#xff0c;它可以高效地将I/O事件通知给应用程序&#xff0c;类似于Linux中的Epoll。 简介 IOCP模型属于一种通讯模型&#xff0c;适用于Windows平台下高负载服务器的一…

理解RESTful架构

2019独角兽企业重金招聘Python工程师标准>>> 原文&#xff1a;http://www.ruanyifeng.com/blog/2011/09/restful.html?20160826000527 越来越多的人开始意识到&#xff0c;网站即软件&#xff0c;而且是一种新型的软件。 这种"互联网软件"采用客户端/服务…

凡是过往,皆为序章。

凡是过往&#xff0c;皆为序章今天是元旦假期的最后一天&#xff0c;这三天我一直在想&#xff0c;21年的年终总结应该如何下笔。其实心里面想表达和记录的事情很多&#xff0c;可当真正坐在电脑前时&#xff0c;却发现没有头绪。贵有恒&#xff0c;何必三更起五更眠。最无益&a…

查看操作系统版本linux_LINUX操作系统常用操作收录(二):查看文件内容命令小结...

先整体了解一下如何查看文件内容的命令vi 兼有修改功能的查看方式&#xff0c;会单独打开整个文件vim 可修改文件内容并且显示当前查看位置在文件中的%多少cat 由第一行开始显示内容&#xff0c;并将所有内容输出tac 从最后一行倒序显示内容&#xff0c;并将所有内容输出more…

crond定时任务详细分析

一、定时任务crond的介绍 crond是linux系统中用来定期执行命令或指定程序任务的一种服务或软件。一般情况下&#xff0c;我们安装文成系统之后&#xff0c;默认变回启动crond任务调度服务&#xff0c;crond服务会定期(默认每分钟检查一次)检查系统中是否有要执行的任务工作。…

OCS2007R2升级LyncSrv2013 PART4:关联边缘

完成拓扑的合并后&#xff0c;由于边缘服务器尚未做迁移和升级&#xff0c;所以此时我们的Lync Server没有边缘服务、联盟路由等。我们就可以把OCS的边缘服务器与Lync Server前端进行关联&#xff0c;暂时使用OCS的联盟路由和边缘服务。要关联OCS边缘服务器&#xff0c;需要打开…

2021技术文大盘点 | 打包过去,​面向未来

先用四句诗词快速描述 一下我的写作心得1. 只在此山中&#xff0c;云深不知处作为开发人员&#xff0c;常执着于机器0,1代码&#xff0c;非假既真&#xff1b;真实世界是很主观的&#xff0c;需要精致细节&#xff0c;更多时候需要全局把控。带着问题写作&#xff0c;对事物理解…

Ansible 一步一步从入门到精通(一)

一&#xff1a;安装ansiblemac&#xff1a;1. 安装 Homebrew (get the installation command from the Homebrew website).2. 安装Python 2.7.x ( brew install python ).3. 安装 Ansible ( sudo pip install ansible ).linux&#xff1a;如果系统中安装了python-pip和python-d…

客户细分总结

随着营销方式的多变、客户需求各异、营销增长受阻等多方面影响&#xff0c;企业的营销面临前所未有的挑战和机遇&#xff0c;精准化营销似乎已成为很多公司的选择&#xff0c;本文针对以下客户细分五大模块进行总结&#xff1a; 一&#xff1a;客户细分的必要性&#xff1a; 顾…