redis介绍
官方介绍:
Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs and geospatial indexes with radius queries. Redis has built-in replication, Lua scripting, LRU eviction, transactions and different levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic partitioning with Redis Cluster.
redis作为nosql(非关系型数据库)其中一种,是一个高性能的key-value数据库,相比于支持string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型),可以将存储在内存的键值对数据持久化到硬盘,可以使用复制特性来扩展读性能,还可以使用客户端分片来扩展写性能。
更多redis介绍:
- 官网:https://redis.io/
- 学习Redis从这里开始:http://www.epubit.com.cn/article/200
redis在windows下载和使用
要下载windows版本的redis,必须要有redis-server.exe:服务程序(之前在官网下没有这个文件,不知道是因为版本问题还是不是windows版本的问题)
windows的下载版本:http://download.csdn.net/download/jimlung/9609681
Linux版教程本:http://blog.csdn.net/chenggong2dm/article/details/6100001
遇到的问问题:
[3416] 05 Jan 11:38:39.089 # Warning: no config file specified, using the defaul
t config. In order to specify a config file use redis-server /path/to/redis.conf
[3416] 05 Jan 11:38:39.109 # Creating Server TCP listening socket *:6379: bind:
No such file or directory
或者遇到
Creating Server TCP listening socket 127.0.0.1:6379: bind: No error
解决方法遇到上面的错误
- 一种情况是你没有指定redis的配置文件,他会使用默认的redis.conf文件,而windows里的是redis.windows.conf。你可以启动命令台输入:redis-server redis.windows.conf
- 还有一种是已经启用的redis,导致6379端口被占用,把原来的关闭即可。
- 依次使用下列命令
- redis-cli.exe
- shutdown
- exit
- redis-server.exe
成功打开后即可看见成功界面:
这样我们相当于启动了redis的服务器,当我们使用redis时,必须开着这个窗口。
使用redis
完成上面的步骤后,另开一个cmd窗口,运行redis-cli.exe程序,即可运行redis。
127.0.0.1:6379> set a aa
OK
127.0.0.1:6379> get a
"aa"
我们保存了key为a的字符串aa,在获取了名字为a的字符串,redis的使用是不是很简单呢。当然我们还可以保存列表,集合等5种不同的数据类型。
redis的全面的使用手册:http://www.yiibai.com/redis/redis_quick_guide.html
在java使用redis
maven的包:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
@Test
public void testRedis() {
Jedis jj = new Jedis("localhost");
jj.set("key1", "I am value 1");
String ss = jj.get("key1");
System.out.println(ss);
}
通过测试可以获取正确的字符串,并且从redis-cli.exe也可以获取到在java中保存的字符串。
redis集成于spring框架并使用
一样需要导入maven包。
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
创建redis的配置文件 redis.properties
#redis config
redis.pass=
redis.pool.maxTotal=105
redis.pool.maxIdle=10
redis.pool.maxWaitMillis=5000
redis.pool.testOnBorrow=true
#redis \u5355\u8282\u70B9\u914D\u7F6E
redis.ip=127.0.0.1
redis.port=6379
spring的配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 缓存的层级 -->
<context:component-scan base-package="com.yingjun.ssm.cache" />
<!-- 引入redis配置 -->
<context:property-placeholder location="classpath:redis.properties"
ignore-unresolvable="true" />
<!-- redis单节点数据库连接配置 -->
<bean id="jedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="${redis.ip}" />
<property name="port" value="${redis.port}" />
<property name="password" value="${redis.pass}" />
<property name="poolConfig" ref="jedisPoolConfig" />
</bean>
<!-- redisTemplate配置,redisTemplate是对Jedis的对redis操作的扩展,有更多的操作,封装使操作更便捷 -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>
</beans>
redis的工具类
package com.yingjun.ssm.cache;
import com.yingjun.ssm.util.ProtoStuffSerializerUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Set;
/**
* redis缓存
*
* @author yingjun
*
*/
@Component
public class RedisCache {
public final static String CAHCENAME="cache";//缓存名
public final static int CAHCETIME=60;//默认缓存时间
//主要通过注入的redisTemplate对redis进行操作
@Autowired
private RedisTemplate<String, String> redisTemplate;
public <T> boolean putCache(String key, T obj) {
final byte[] bkey = key.getBytes();
final byte[] bvalue = ProtoStuffSerializerUtil.serialize(obj);
boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
return connection.setNX(bkey, bvalue);
}
});
return result;
}
public <T> void putCacheWithExpireTime(String key, T obj, final long expireTime) {
final byte[] bkey = key.getBytes();
final byte[] bvalue = ProtoStuffSerializerUtil.serialize(obj);
redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
connection.setEx(bkey, expireTime, bvalue);
return true;
}
});
}
public <T> boolean putListCache(String key, List<T> objList) {
final byte[] bkey = key.getBytes();
final byte[] bvalue = ProtoStuffSerializerUtil.serializeList(objList);
boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
return connection.setNX(bkey, bvalue);
}
});
return result;
}
public <T> boolean putListCacheWithExpireTime(String key, List<T> objList, final long expireTime) {
final byte[] bkey = key.getBytes();
final byte[] bvalue = ProtoStuffSerializerUtil.serializeList(objList);
boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
connection.setEx(bkey, expireTime, bvalue);
return true;
}
});
return result;
}
public <T> T getCache(final String key, Class<T> targetClass) {
byte[] result = redisTemplate.execute(new RedisCallback<byte[]>() {
@Override
public byte[] doInRedis(RedisConnection connection) throws DataAccessException {
return connection.get(key.getBytes());
}
});
if (result == null) {
return null;
}
return ProtoStuffSerializerUtil.deserialize(result, targetClass);
}
public <T> List<T> getListCache(final String key, Class<T> targetClass) {
byte[] result = redisTemplate.execute(new RedisCallback<byte[]>() {
@Override
public byte[] doInRedis(RedisConnection connection) throws DataAccessException {
return connection.get(key.getBytes());
}
});
if (result == null) {
return null;
}
return ProtoStuffSerializerUtil.deserializeList(result, targetClass);
}
/**
* 精确删除key
*
* @param key
*/
public void deleteCache(String key) {
redisTemplate.delete(key);
}
/**
* 模糊删除key
*
* @param pattern
*/
public void deleteCacheWithPattern(String pattern) {
Set<String> keys = redisTemplate.keys(pattern);
redisTemplate.delete(keys);
}
/**
* 清空所有缓存
*/
public void clearCache() {
deleteCacheWithPattern(RedisCache.CAHCENAME+"|*");
}
}
这样我们在我们的项目里可以使用RedisCache这个类里的方法来获取我们的缓存了。
@Autowired
private RedisCache cache;
public List<Goods> getGoodsList(int offset, int limit) {
String cache_key = RedisCache.CAHCENAME + "|getGoodsList|" + offset + "|" + limit;
List<Goods> result_cache = cache.getListCache(cache_key, Goods.class);
if (result_cache != null) {
LOG.info("get cache with key:" + cache_key);
} else {
// 缓存中没有再去数据库取,并插入缓存(缓存时间为60秒)
result_cache = goodsDao.queryAll(offset, limit);
cache.putListCacheWithExpireTime(cache_key, result_cache, RedisCache.CAHCETIME);
LOG.info("put cache with key:" + cache_key);
return result_cache;
}
return result_cache;
}
上面的例子是先从redis内存中获取,如果不为空,则不用从数据库中获取,如果为空从数据库中获取在把数据保存到redis中,以便下次获取。
完整的例子github:https://github.com/lkj41110/beauty_ssm/tree/master/src
当然redis还有很多用处,目前项目里只是把它作为一个缓存的机制来减少对数据库的读取加快数据的读取速度