由於目前僅僅通過mysql來進行資料的儲存,要完成複雜的資料統計耗時較長。因此考慮將部分資料匯入到redis中,完成資料統計後,再將結果存入mysql。
經查資料,利用管道的方式可以繞開第三方的資料互動過程,資料直接從mysql匯入到redis的速度非常快。在筆者的測試環境中,500w層級的資料大概用時40秒(當然了,與mysql的查詢耗時有關)。
另外,由於mysql表設計的問題,大部分資料存放區在結構相同的不同表中。比如表A儲存了使用者"啟動應用"這個事件數目據, 表B儲存了使用者"開啟設定頁面"的事件數目據, 但是表A和表B的結構都是一樣的。 目前在通過mysql來做資料統計時,是按順序的來進行操作,統計完了A,再統計B。
而在redis中,表A和表B的資料和以放在同一個資料庫中,然後利用set之類的容器將各個事件的資料分類儲存起來,遍曆一次便可以完成所有事件數目據的統計。
因此,現在的應用情境為: 大量匯出mysql中各個表的相同條件的資料(如同為某一天的資料), 匯入redis,最後合并完成統計。具體的匯出匯入代碼如下所示(mysql2redis.sh):
!/bin/bashmysql_host=192.168.x.xxmysql_user=xiaomomysql_pwd=xiaomo database=test_dbtbls_prefix="test_tbl_name_prefix"#調用shell時,傳入的日期參數cur_dt="$1" #遍曆表,返回表名listtable_list=$(mysql -h$mysql_host -u$mysql_user -p$mysql_pwd $database -A -Bse "show tables") function gen_sql(){ src_tbl=$1 mysql2redis="SELECT CONCAT(\ '*10\r\n',\ '$', LENGTH(redis_cmd), '\r\n',redis_cmd, '\r\n',\ '$', LENGTH(redis_key), '\r\n',redis_key, '\r\n',\ '$', LENGTH(hkey1), '\r\n', hkey1, '\r\n',\ '$', LENGTH(hval1), '\r\n', hval1, '\r\n',\ '$', LENGTH(hkey2), '\r\n', hkey2, '\r\n',\ '$', LENGTH(hval2), '\r\n', hval2, '\r\n',\ '$', LENGTH(hkey3), '\r\n', hkey3, '\r\n',\ '$', LENGTH(hval3), '\r\n', hval3, '\r\n',\ '$', LENGTH(hkey4), '\r\n', hkey4, '\r\n',\ '$', LENGTH(hval4), '\r\n', hval4, '\r'\ )\ FROM (\ SELECT\ 'HMSET' AS redis_cmd, uniq_id AS redis_key,\ 'f1' AS hkey1, f1 AS hval1,\ 'f2' AS hkey2, f2 AS hval2,\ 'f3' AS hkey3, f3 AS hval3,\ 'f4' AS hkey4, f4 AS hval4\ FROM $src_tbl WHERE dt='$cur_dt'\ ) AS T" echo "$mysql2redis"}prefix_len=$(expr length $tbls_prefix)for arg in $table_listdo if [[ "${arg:0:$prefix_len}" == ${tbls_prefix} ]] # 判斷表名是否匹配(表名以指定首碼開頭) then mysql2redisCmd=$(gen_sql $arg) echo $mysql2redisCmd | mysql -u$mysql_user -p$mysql_pwd -h$mysql_host $database --skip-column-names --raw | redis-cli -n 1 --pipe fi done
調用樣本: /bin/bash mysql2redis.sh 2014-03-08
另: 可參考redis的resp協議文檔 http://redis.io/topics/protocol