First, Redis introduction
what is Redis?
Redis is a key-value storage system. Like memcached, it supports a relatively greater number of stored value types, including string (string), list (linked list), set (set), Zset (sorted set-ordered set), and hash (hash type). These data types support Push/pop, Add/remove and intersection-set and differential sets and richer operations, and these operations are atomic. On this basis, Redis supports a variety of different ways of ordering. As with memcached, data is cached in memory to ensure efficiency. The difference is that Redis periodically writes the updated data to the disk or writes the modification operation to the appended record file, and on this basis, it realizes the Master-slave (master-slave) synchronization.
What is the characteristic of it?
(1) The Redis database is fully in memory, using the disk for persistence only.
(2) Redis has a richer set of data types than many key-value data stores.
(3) Redis can copy data to any number of servers.
Redis Advantage?
(1) Exceptionally fast: the speed of Redis is very fast, can perform about 110,000 sets per second, about 81000 + records per second.
(2) Support rich data types: Redis support Most developers already know like lists, collections, ordered collections, hash data types. This makes it very easy to solve a wide variety of problems because we know which problems can be handled better by its data type.
(3) The operation is atomic: All Redis operations are atomic, which ensures that if two clients simultaneously access the Redis server, the updated value will be obtained.
(4) Multifunction utility: Redis is a versatile tool that can be used in multiple applications such as caching, message, queue use (Redis native support publish/subscribe), any transient data, application, such as Web application sessions, Web page hit count, etc.
Redis shortcomings?
(1) Single thread
(2) Memory consumption
Ii. Examples of Use
This article uses maven+eclipse+sping
1, the introduction of jar bag
<!--redis start-->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.6.1.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
< artifactid>jedis</artifactid>
<version>2.7.3</version>
</dependency>
<!--Redis End-->
2, Configuration Bean
Add the following configuration to the Application.xml
<!--Jedis configuration--> <bean id= "Poolconfig" class= "Redis.clients.jedis.JedisPoolConfig" > <property n
Ame= "Maxidle" value= "${redis.maxidle}"/> <property name= "Maxwaitmillis" value= "${redis.maxwait}"/> <property name= "Testonborrow" value= "${redis.testonborrow}"/> </bean > <!--redis Server Center--> < Bean id= "ConnectionFactory" class= "Org.springframework.data.redis.connection.jedis.JedisConnectionFactory" > & Lt;property name= "Poolconfig" ref= "Poolconfig"/> <property name= "port" value= "${redis.port}"/> <
Property Name= "HostName" value= "${redis.host}"/> <property name= "password" value= "${redis.password}"/> <property name= "Timeout" value= "${redis.timeout}" ></property> </bean > <bean id= "redistemp Late "class=" Org.springframework.data.redis.core.RedisTemplate "> <property name=" connectionfactory "ref=" con
Nectionfactory "/><property name= "Keyserializer" > <bean class= "org.springframework.data.redis.serializer.StringRedisSerial" Izer "/> </property> <property name=" ValueSerializer "> <bean class=" org.springframe Work.data.redis.serializer.JdkSerializationRedisSerializer "/> </property> </bean > <!-- Cache configuration--> <bean id= "Methodcacheinterceptor" class= "Com.mucfc.msm.common.MethodCacheInterceptor" > ;p roperty name= "Redisutil" ref= "Redisutil"/> </bean > <bean id= "redisutil" class= "Com.mucfc.msm.common". Redisutil "> <property name=" redistemplate "ref=" redistemplate "/> </bean >
The configuration file Redis Some of the configuration data redis.properties as follows:
#redis中心
redis.host=10.75.202.11
redis.port=6379
redis.password=123456
redis.maxidle=100
redis.maxactive=300
redis.maxwait=1000
redis.testonborrow=true
redis.timeout=100000
# classes that do not need to be added to the cache
Targetnames=xxxrecordmanager,xxxsetrecordmanager,xxxstatisticsidentificationmanager
# methods
that do not require caching methodnames=
#设置缓存失效时间
com.service.impl.xxxrecordmanager=
com.service.impl.xxxsetrecordmanager=
defaultcacheexpiretime=3600
To sweep these properties files, add the following configuration to the Application.xml
<!--introduce properties profile-->
<bean id= "Propertyconfigurer" class= " Org.springframework.beans.factory.config.PropertyPlaceholderConfigurer ">
<property name=" Locations " >
<list>
<value>classpath:properties/*.properties</value>
<!--If you have more than one configuration file, Just keep adding here-->
</list>
</property>
3, some tool class
(1) redisutil
In the above Bean, Redisutil is the instance used to cache and remove data
Package Com.mucfc.msm.common;
Import java.io.Serializable;
Import Java.util.Set;
Import Java.util.concurrent.TimeUnit;
Import Org.apache.log4j.Logger;
Import Org.springframework.data.redis.core.RedisTemplate;
Import org.springframework.data.redis.core.ValueOperations; /** * Redis Cache Tool Class */Public final class Redisutil {private Logger Logger = Logger.getlogger (redisutil.cla
SS);
Private redistemplate<serializable, object> redistemplate; /** * Bulk Delete corresponding value * * @param keys/public void Remove (final string ... keys) {for string key:
Keys) {remove (key);
}/** * Bulk Delete key * * @param pattern */public void Removepattern (final String pattern) {
set<serializable> keys = Redistemplate.keys (pattern);
if (keys.size () > 0) redistemplate.delete (keys); /** * Delete the corresponding value * * @param key/public void remove (final String key) {if ExiSTS (key)) {Redistemplate.delete (key); }/** * Determines if there is a corresponding value in the cache * * @param key * @return/public Boolean exists (final String K
EY) {return redistemplate.haskey (key); /** * Read Cache * * @param key * @return */public Object get (final String key) {Object res
Ult = null;
Valueoperations<serializable, object> operations = redistemplate. Opsforvalue ();
result = Operations.get (key);
return result; /** * Write Cache * * @param key * @param value * @return/public Boolean set (final String ke
Y, Object value) {Boolean result = false;
try {valueoperations<serializable, object> operations = redistemplate. Opsforvalue ();
Operations.set (key, value);
result = true;
catch (Exception e) {e.printstacktrace ();
return result; /** * Write Cache * @param key * @paraM value * @return */public Boolean set (Final String key, Object value, Long expiretime) {Boolean result
= false;
try {valueoperations<serializable, object> operations = redistemplate. Opsforvalue ();
Operations.set (key, value);
Redistemplate.expire (Key, Expiretime, timeunit.seconds);
result = true;
catch (Exception e) {e.printstacktrace ();
return result; } public void Setredistemplate (redistemplate<serializable, object> redistemplate) {this.redistemp
late = Redistemplate; }
}
The
(2) Methodcacheinterceptor
Slice Methodcacheinterceptor, which is used to give different methods to join the judge if the cache exists data, the data is fetched from the cache. Otherwise, the data is fetched from the database for the first time, and the results are saved to the cache.
Package Com.mucfc.msm.common;
Import Java.io.File;
Import Java.io.FileInputStream;
Import Java.io.InputStream;
Import java.util.ArrayList;
Import java.util.List;
Import java.util.Properties;
Import Org.aopalliance.intercept.MethodInterceptor;
Import org.aopalliance.intercept.MethodInvocation;
Import Org.apache.log4j.Logger; public class Methodcacheinterceptor implements Methodinterceptor {private Logger Logger = Logger.getlogger (methodcache
Interceptor.class);
Private Redisutil Redisutil; Private list<string> targetnameslist; Do not add the cached service name private list<string> methodnameslist; Method names not added to the cache private Long defaultcacheexpiretime; Cache default Expiration time private long xxxrecordmanagertime; Private Long Xxxsetrecordmanagertime; /** * Initialization read does not need to add the cached class name and method name/public methodcacheinterceptor () {try {file F = new file ("D : \\lunaJee-workspace\\msm\\msm_core\\src\\main\\java\\com\\mucfc\\msm\\common\\cacheConf.propertiEs ");
The configuration file location is directly written dead, has to be modified under inputstream in = new FileInputStream (f); InputStream in = GetClass (). getClassLoader (). getResourceAsStream (//"D:\\lunajee-workspace\\msm\\msm_core
\\src\\main\\java\\com\\mucfc\\msm\\common\\cacheConf.properties ");
Properties P = new properties ();
P.load (in);
Split string string[] Targetnames = P.getproperty ("Targetnames"). Split (",");
string[] Methodnames = P.getproperty ("Methodnames"). Split (",");
Load expiration Setting Defaultcacheexpiretime = long.valueof (P.getproperty ("Defaultcacheexpiretime"));
Xxxrecordmanagertime = long.valueof (P.getproperty ("Com.service.impl.xxxRecordManager"));
Xxxsetrecordmanagertime = long.valueof (P.getproperty ("Com.service.impl.xxxSetRecordManager"));
Create List targetnameslist = new arraylist<string> (targetnames.length);
Methodnameslist = new arraylist<string> (methodnames.length); Integer MaxLen = TargetnamEs.length > Methodnames.length?
TargetNames.length:methodNames.length;
Add class names and method names that do not require caching to the list for (int i = 0; i < MaxLen; i++) {if (I < targetnames.length) {
Targetnameslist.add (Targetnames[i]);
} if (I < methodnames.length) {Methodnameslist.add (methodnames[i]);
A catch (Exception e) {e.printstacktrace ());
@Override public Object Invoke (Methodinvocation invocation) throws Throwable {Object value = null;
String targetName = Invocation.getthis (). GetClass (). GetName ();
String methodname = Invocation.getmethod (). GetName (); Content that does not need to be cached//if (!isaddcache (Stringutil.substrforlastdot (targetName), methodname)) {if!isaddcache (targetName
, methodname)) {//The execution method returns the result return Invocation.proceed ();
} object[] arguments = invocation.getarguments (); String key = Getcachekey (TargetName, MethodName,arguments);
SYSTEM.OUT.PRINTLN (key);
try {//To determine if there is a cached if (redisutil.exists (key)) {return redisutil.get (key);
}//write Cache value = Invocation.proceed ();
if (value!= null) {final String TKey = key;
Final Object TValue = value; New Thread (New Runnable () {@Override public void run () {if Tkey.startswith ("Com.serv
Ice.impl.xxxRecordManager ")) {Redisutil.set (TKey, TValue, xxxrecordmanagertime); else if (Tkey.startswith ("Com.service.impl.xxxSetRecordManager")) {Redisutil.set (TKey, TValue, Xxxsetrec
Ordmanagertime);
else {redisutil.set (TKey, TValue, defaultcacheexpiretime);
}}). Start ();
} catch (Exception e) {e.printstacktrace ();
if (value = = null) {return invocation.proceed ();
} return value;
} /** * Add Cache * * @return/private Boolean Isaddcache (String targetName, String methodname) {b
Oolean flag = true;
if (Targetnameslist.contains (targetName) | | | methodnameslist.contains (methodname)) {flag = false;
return flag; /** * Create Cache Key * * @param targetName * @param methodname * @param arguments/private St Ring Getcachekey (String targetName, String methodname, object[] arguments) {StringBuffer SBU = new Stringbuff
ER ();
Sbu.append (TargetName). Append ("_"). Append (methodname);
if ((arguments!= null) && (arguments.length!= 0)) {for (int i = 0; i < arguments.length; i++) {
Sbu.append ("_"). Append (Arguments[i]);
} return sbu.tostring ();
public void Setredisutil (Redisutil redisutil) {this.redisutil = Redisutil;
}
}
4. Configure the classes or methods that need to be cached
Add the following configuration to Application.xml, where multiple classes or methods can be configured to configure multiple
<!--need to add a cached class or method-->
<bean id= "Methodcachepointcut" class= " Org.springframework.aop.support.RegexpMethodPointcutAdvisor ">
<property name=" Advice ">
<ref Local= "Methodcacheinterceptor"/>
</property>
<property name= "Patterns" >
<list>
<!--determine the regular expression list-->
<value>com\.mucfc\.msm\.service\.impl\...*serviceimpl.*</value >
</list>
</property>
</bean >
5, the implementation of the results:
Write a simple unit test as follows:
@Test public
void Getsettunitbysettunitidtest () {
String systemid = "CES";
String Merchantid = "the";
Settunit configsettunit = Settunitservice.getsettunitbysettunitid (SystemID, Merchantid, "ESP");
Settunit configSettUnit1 = Settunitservice.getsettunitbysettunitid (SystemID, Merchantid, "ESP");
Boolean flag= (Configsettunit = = configSettUnit1);
System.out.println (configsettunit);
Logger.info ("Find result" + configsettunit.getbusinesstype ());
Localsecondfifocache.put ("Configsettunit", Configsettunit.getbusinesstype ());
String string = Localsecondfifocache.get ("Configsettunit");
Logger.info ("Find result" + string);
}
This is the first time a unit test has been performed:
Methodcacheinterceptor This class to break the point, and then before each query will first enter this method
Run in turn, find no cache, so go directly to the database
The SQL statement that was printed:
Second execution:
The cache was already written because of the first execution. So the second time you take data directly from the cache
3, take the result of two times to compare the address:
Found that two are not the same object, yes, yes. If you are using Ehcache, then the memory address of the two will be the same. That's because the caching mechanism used by Redis and Ehcache is different. Ehcache is based on the local computer's memory usage cache, so use caching to fetch data directly on the local computer. Converting to a Java object will be the same memory address, and redis it is on the computer with the Redis service (usually another computer), so when the data is transferred to the local, it corresponds to a different memory address, so using = = to compare returns FALSE. But it does come from the cache, which we can see from the breakpoint above.
The above is the entire content of this article, I hope to help you learn.