前段时间做了一个用户访问记录的收集和分析,在设计方案的时候数据的存储和持久化考虑了两种方式,一种是存储到Redis,然后使用Redis的数据持久化方案完成数据持久化;一种是传统的IO写文件方式,就是将收集到的数据写在服务器的txt文件里,再对文件顶起做一个数据库导入动作。虽然最后架构师直接敲定了采用IO的方式,我还是自己写了一个小小的比较,来对比两种方法的效率。
数据的存储和持久化过程整体不是一篇文章能说清楚的,今天先比较第一步,就是数据的存储。
codis数据存储
codis是一个redis的解决方案,其实可以认为是redis外面包了一层壳子,就是用起来更方便一点,这里就不介绍了。直接上代码。
jedis工具类代码
我们利用jedis建立一个连接池,和数据库连接池是相似的概念。虽然这个文章还不会涉及到连接池的应用,但是后面还是像比较一下并发情况下两种方式的效率比较。
代码如下:
package util;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* Created by Vivi on 2017/5/26.
*/
public class CodisConnection {
// 设定连接池的一些常量值
private static final String CODIS_URL = "127.0.0.1";
private static final int CODIS_URL_PORT = 9000;
private static final int POOL_MAX = 100;
private static final int IDEL_MAX = 5;
private static final int WAIT_MAX = 5000;
private static JedisPool pool;
static {
init();
}
public static void init() {
try {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(POOL_MAX);
jedisPoolConfig.setMaxIdle(IDEL_MAX);
jedisPoolConfig.setMaxWaitMillis(WAIT_MAX);
jedisPoolConfig.setTestOnBorrow(true);
pool = new JedisPool(jedisPoolConfig,CODIS_URL,CODIS_URL_PORT);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Jedis getConn() {
if(pool == null) {
return null;
} else {
return pool.getResource();
}
}
public static void closeConn(Jedis resource){
if (pool!= null) {
pool.returnResource(resource);
}
}
}
后面的测试类里我们会使用这个工具类获得和关闭连接。
codis写入数据
public long codisTime(int n)
{
//生成一个任意长度的字符串
RandomUtil randomUtil = new RandomUtil();
String s = randomUtil.generateString(n);
//获取一个jedis连接
CodisConnection codisConnection = new CodisConnection();
Jedis jedis = codisConnection.getConn();
Date start = new Date();
//循环写入一百次
for (int i = 0; i < 100; i++)
{
jedis.set("solutionCampare1" + i, s);
}
Date end = new Date();
System.out.println("codis写入数据的时间开销是:" + (end.getTime() - start.getTime()));
//删除测试数据
for (int j = 0; j < 100; j++)
{
jedis.del("solutionCampare1" + j);
}
if (jedis != null)
{
codisConnection.closeConn(jedis);
}
return end.getTime() - start.getTime();
}
这里用到了一个自己写的工具类,是用来生成一个随机字符串的工具类,也贴在这里:
package util;
import java.util.Random;
/**
* Created by Vivi on 2017/5/26.
*/
public class RandomUtil
{
public String generateString(int length)
{
String base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random = new Random();
StringBuilder stringBuilder = new StringBuilder("");
for (int i = 0; i < length; i++)
{
stringBuilder.append(base.charAt(random.nextInt(base.length())));
}
System.out.println(stringBuilder.length() + "--------" + stringBuilder.toString());
return stringBuilder.toString();
}
}
一次写入的时间开销
运行上面的测试代码,codis的时间开销是:
codis写入100次的时间为:194
IO数据存储
测试代码
IO存储就比较简单了,不需要连接池什么东西的,只是也会用到上面的工具类,测试代码如下:
public long IOTime(int n) throws Exception
{
//生成一个任意长度的字符串
RandomUtil randomUtil = new RandomUtil();
String s = randomUtil.generateString(n);
//写入文件一百次
String fileName = "L:" + File.separator + "IoTest.txt";
File file = new File(fileName);
Writer out = new FileWriter(file);
Date start = new Date();
for (int i = 0; i < 100; i++)
{
out.write(s);
}
Date end = new Date();
out.close();
System.out.println(end.getTime() - start.getTime());
return end.getTime() - start.getTime();
}
运行结果
这个控制台的输出是这样的:
IO的时间开销是:1
初步结果
IO比codis快。。。。很多很多,但是这个结果并不能证明codis效率低,因为考虑到并发的情况,受限于系统资源,codis的优势才会发挥出来。这个结果只能证明codis打开一个链接需要花费时间。下一篇文章写并发情况下的对比。