前言
关于Redis的持久化方式共有两种。RDB
和AOF
。
可以看先前的文章《redis和memcached 对比》。
测试目的
1:测试多种数据结构的操作方式。
2:测试持久化的效果。
3:客户端Java编写(Jedis)。
4:打开密码校验
过程
下载安装Redis
(忽略)
创建Maven工程
在pom.xml中添加如下依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
</dependency>
设置密码
打开配置文件。
打开密码设置
搜索requirepass
结果为:
#requirepass foobared
修改配置
requirepass mypwd
RDB测试
修改RDB的设置
搜索 "save 900 1"
可以看到如下的配置
save 900 1
save 300 10
save 60 10000
save N M 意思就是N秒内执行了M次操作然后执行持久化
添加
save 30 100
30秒内执行了100次操作
在这个配置的下面顺序有很多相关的参数可以配置,这里我们修改一下备份文件的路径
这个是备份的文件名称
dbfilename dump.rdb
修改为
dbfilename mydump.rdb
持久化文件保存的路径,默认是当前路径
dir ./
修改为dumps路径下
dir dumps
编写Java代码
RedisClient代码,
package cn.test.redis;
import java.util.concurrent.locks.ReentrantLock;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* Redis连接的对象
* @author Administrator
*
*/
public class RedisClient
{
private JedisPool jedisPool;
private static RedisClient redisClient;
/**
* 保证并发的时候效率最高
*/
private static ReentrantLock lock=new ReentrantLock();
private RedisClient()
{
initialPool();
}
/**
* 单例
* @return
*/
public static RedisClient gi()
{
if (redisClient == null)
{
lock.lock();
if (redisClient == null)
{
redisClient = new RedisClient();
}
lock.unlock();
}
return redisClient;
}
/**
* 获得一个连接
* @return
*/
public Jedis getJedis()
{
return jedisPool.getResource();
}
/**
* 初始化连接池
*/
private void initialPool()
{
// 池基本配置
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(20);
config.setMaxIdle(5);
config.setMaxWaitMillis(1000l);
config.setTestOnBorrow(false);
//这里设置了超时时间和密码
jedisPool = new JedisPool(config, "127.0.0.1", 6379,Protocol.DEFAULT_TIMEOUT,"mypwd");
}
public void Close()
{
jedisPool.close();
}
}
测试连接是否成功
public class TestPersist
{
public static void main(String[] args)
{
System.out.println(RedisClient.gi().getJedis().ping());
}
}
运行后显示的内容,表示连接成功。
PONG
完整的测试代码
package cn.test.redis;
import java.util.Map;
import java.util.Map.Entry;
import redis.clients.jedis.Jedis;
public class TestPersist
{
public static void main(String[] args)
{
System.out.println(RedisClient.gi().getJedis().ping());
saveData();
//readData();
}
static String listName = "myList";
static String hashName = "myHash";
/**
* 先执行数据存储
*/
public static void saveData()
{
int i = 0;
Jedis jedis = RedisClient.gi().getJedis();
// string
for (i = 0; i < 100; i++)
{
jedis.set("key" + i, "value" + i);
}
// list 添加内容
for (i = 0; i < 100; i++)
{
jedis.lpush(listName, "listValue" + i);
}
long length=jedis.llen(listName);
System.out.println("myList size="+length);
// 设置hash内容
for (i = 0; i < 100; i++)
{
jedis.hset(hashName, "h_key_" + i, "h_value_" + i);
}
length=jedis.hlen(hashName);
System.out.println("myHash length="+length);
}
/**
* 然后停止服务,重新启动服务,执行读取数据。 当然,需要我们等待60秒
*/
public static void readData()
{
int i = 0;
Jedis jedis = RedisClient.gi().getJedis();
// string
for (i = 0; i < 100; i++)
{
System.out.println("----Delete---key-----"+jedis.get("key" + i));
jedis.del("key" + i);
}
/////////////////////////////// list
long length=jedis.llen(listName);
System.out.println("myList size="+length);
for (i = 0; i < length; i++)
{
System.out.println("--Remove-List---"+jedis.lpop(listName));
}
/////////////////////////////hash
length=jedis.hlen(hashName);
System.out.println("myHash length="+length);
Map<String,String> hashMap=jedis.hgetAll(hashName);
String[] keys=new String[(int)length];
i=0;
for(Entry<String,String> entry:hashMap.entrySet())
{
System.out.println("-----(key="+entry.getKey()+",value="+entry.getValue()+")---");
keys[i++]=entry.getKey();
}
System.out.println("deleNum="+jedis.hdel(hashName, keys));
}
}
运行后输出的内容
PONG
myList size=100
myHash length=100
观察控制台的输出,当输出类似如下的内容,表示执行了存储,可以查看dumps/mydump.rdb生成了。
[10924] 19 Dec 16:05:28.020 * 100 changes in 30 seconds. Saving…
[10924] 19 Dec 16:05:28.058 * Background saving started by pid 10160
[10924] 19 Dec 16:05:28.259 # fork operation complete
[10924] 19 Dec 16:05:28.261 * Background saving terminated with success
停止redis,然后重新启动。
注释存储,打开读取。
修改代码
//saveData();
readData();
输出如下:
PONG
----Delete---key-----value0
----Delete---key-----value1
----Delete---key-----value2
........
----Delete---key-----value98
----Delete---key-----value99
myList size=100
--Remove-List---listValue99
--Remove-List---listValue98
--Remove-List---listValue97
..........
--Remove-List---listValue3
--Remove-List---listValue2
--Remove-List---listValue1
--Remove-List---listValue0
myHash length=100
-----(key=h_key_0,value=h_value_0)---
-----(key=h_key_1,value=h_value_1)---
-----(key=h_key_2,value=h_value_2)---
.........
-----(key=h_key_10,value=h_value_10)---
-----(key=h_key_98,value=h_value_98)---
-----(key=h_key_11,value=h_value_11)---
-----(key=h_key_99,value=h_value_99)---
deleNum=100
注,Redis默认的持久化的方式就是RDB,而且默认是开启的状态。
测试AOF
修改配置
搜索appendonly
appendonly no
修改为
appendonly yes
表示开启了AOF功能。
搜索appendfsync
appendfsync everysec
默认就是每秒进行同步。
修改Java代码
saveData();
//readData();
执行多次saveData()。
发现aof文件变大了,记住文件大小。
通过reids-cli连接redis。
执行
>BGREWRITEAOF
这时检查aof文件,发现文件大小小了很多。
但是这样手动操作实在是太不科学了,怎么办?
是的,利用crontab来执行计划任务是可以的。。
实际上redis提供了自动的sync的机制。
只要开启了aof功能,自动rewriteaof的功能就开启了,不过他的执行是有一个条件的。
首先需要了解一个数值auto_aofrewrite_base_size
。
这个值并没有出现在配置文件中,这个值得意思是每次执行BGREWRITEAOF
后,redis内部用这个值表示当前的aof文件的大小。知道这个值的意思就好弄了。
接下来看看另外两个参数,这两个参数在配置文件中,可以进行修改。
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
以上是默认值
auto-aof-rewrite-percentage
的意思就是当前的aof文件的大小超出auto_aofrewrite_base_size
大小的百分比执行rewrite操作。100表示是当前的两倍。
auto-aof-rewrite-min-size
的意思就是当前的aof文件必须大于64m的时候才会执行rewrite。
后记
两种持久化方式可以同时使用,可以根据具体场景来选择持久化方案,或者两者同时开启!
参考文章:
http://blog.csdn.net/u011129848/article/details/51527287
http://blog.csdn.net/zyz511919766/article/details/42268219
http://blog.csdn.net/jsjwk/article/details/7971033
http://www.yiibai.com/redis/