前段時間做了一個用戶訪問記錄的收集和分析,在設計方案的時候數據的存儲和持久化考慮了兩種方式,一種是存儲到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打開一個鏈接需要花費時間。下一篇文章寫併發情況下的對比。