Redis是什么(来源百度百科)
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。
redis是一个key-value存储系统。它支持存储的value类型相对更多,包括string(字符串)、list(链表、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis 是一个高性能的key-value数据库。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。
更详细的介绍参见 百度百科:Redis
Redis应用场景
redis目前在互联网公司用的非常非常多,主要是作为内存数据库使用,常用的使用场景包括以下几部分:
- 1、key-value数据库,比如短信验证码存储,邮件验证链接存储
- 2、电商的购物车
- 3、秒杀,主要基于Redis的原子操作
- 4、session共享,主要用于web服务器集群间的session共享
- 5、模拟队列,消息处理异步
- 6、app端用户状态存储
- 7、。。。
Redis的安装
Redis的安装非常简单,不光支持linux,还支持window是,不过windows不建议生产环境下使用
windows安装的时候根据操作系统选择32位还是64位的
Redis的图形化工具
Redis的图形化工具还是比较多的,主要为新手提供一个方便。正常生产维护中是不会用图形化工具的。
常见的图形化工具有
- 1、Redis Desktop Manager
- 2、Redis Sdudio
这两款稍微好一些,在数据量大时也经常假死,而且只能显示简单的数据类型,比如string,不支持复杂数据类型。
Redis在java使用
添加redis依赖
pom.xml
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
java连接redis是通过jedis客户端连接的。
redis.properties配置文件
redis.host=127.0.0.1
redis.port=6379
redis.database=
redis.pass=
redis.maxIdle=300
redis.testOnBorrow=true
-
host
指redis服务器ip -
port
指端口,默认6379 -
database
指redis数据存储的单元,从0-15,默认0 -
pass
指连接redis服务器的密码,默认是不需要密码的,如果设置密码后这地方就需要设置一下。 -
maxIdle
指最大空闲数,数据库连接的最大空闲时间。超过空闲时间,数据库连接将被标记为不可用,然后被释放 -
testOnBorrow
在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的
这里面只要设置host和port就可以访问了。
JedisPoolUtil 连接池
public class JedisPoolUtil {
private static String ADDR = "localhost";
//Redis的端口号
private static int PORT = 6379;
//访问密码
private static String AUTH = "admin";
//可用连接实例的最大数目,默认值为8;
//如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
private static int MAX_ACTIVE = 1024;
//控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。
private static int MAX_IDLE = 200;
//等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;
private static int MAX_WAIT = 10000;
private static int TIMEOUT = 10000;
//在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
private static boolean TEST_ON_BORROW = true;
private static JedisPool jedisPool = null;
public static Properties properties = null;
private static String confPath = "/redis.properties";//定义配置文件路径
/**
* 初始化Redis连接池
*/
static {
try {
InputStream is = RedisUtil.class.getResourceAsStream(confPath);
properties = new Properties();
properties.load(is);
MAX_IDLE = Integer.parseInt(properties.get("redis.maxIdle").toString());
TEST_ON_BORROW = Boolean.parseBoolean(properties.get("redis.testOnBorrow").toString());
ADDR = properties.get("redis.host").toString();
PORT = Integer.parseInt(properties.getProperty("redis.port"));
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxIdle(MAX_IDLE);
config.setTestOnBorrow(TEST_ON_BORROW);
jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取Jedis实例
*
* @return
*/
public synchronized static Jedis getJedis() {
try {
if (jedisPool != null) {
Jedis resource = jedisPool.getResource();
return resource;
} else {
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 释放jedis资源
*
* @param jedis
*/
public static void returnResource(final Jedis jedis) {
if (jedis != null) {
jedis.close();
}
}
}
这里写了一个redis连接池,通过读取配置文件,采用单例模式,来建立连接池。
SerializeUtil序列化工具
public class SerializeUtil {
public static byte[] serialize(Object object) {
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
try {
// 序列化
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return bytes;
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
public static Object deserialize(byte[] bytes) {
ByteArrayInputStream bais = null;
try {
// 反序列化
bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
在存储redis时,key和value都需要进行序列化操作,然后取出时,在反序列化,这样就能保证redis的存储和语言无关。
RedisUtil 操作工具类
public class RedisUtil {
/**
* 设置值
*
* @param key
* @param value
*/
public static void set(String key, Object value) {
JedisPoolUtil.getJedis().set(SerializeUtil.serialize(key), SerializeUtil.serialize(value));
}
/**
* 设置值,并设置保存时间
*
* @param key
* @param value
* @param secs 秒数
*/
public static void set(String key, Object value, int secs) {
JedisPoolUtil.getJedis().setex(SerializeUtil.serialize(key), secs, SerializeUtil.serialize(value));
}
/**
* 根据key取值
*
* @param key
* @return
*/
public static Object get(String key) {
return SerializeUtil.deserialize(JedisPoolUtil.getJedis().get(SerializeUtil.serialize(key)));
}
/**
* 删除
*
* @param key
*/
public static void del(String key) {
JedisPoolUtil.getJedis().del(SerializeUtil.serialize(key));
}
public static void main(String[] args) {
RedisUtil.set("com:critc:name", "jack");
System.out.println(RedisUtil.get("com:critc:name").toString());
RedisUtil.del("com:critc:name");
}
}
这里设置了一个redis工具类,可以直接通过key和value赋值,取值,设置过期时间等等。
这里说一下redis的key命名规则,为了更好的存储,key的命名方式是com:critc:app:name:
,即通过:进行分隔,多个小单元组成一整个key
源码下载
[本工程详细源码]
(https://github.com/chykong/java_component/tree/master/chapter3_1_redis)