效能提升 48 倍! python redis 批量寫入大量資料優化過程
背景
- 最近在測試大資料時,需要往redis大寫入大量資料
1.最原始的版本,直接使用hset,效率很低
寫30w條完耗時365秒,這樣有兩個問題:
- 相同的key,寫入多條應該用hmset代替hset
- 另外可以用pipeline,避免頻繁跟redis服務端互動,大量減少網路io
def get_conn():
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
return r
def test_set_redis():
conn = get_conn()
machineId = 43696000000000
device_no = 88800000
work_in = time.time()
source = "1"
factory_no = "factory"
today = datetime.date.today()
oneday = datetime.timedelta(days=1)
tomorrow = str(today + oneday).replace("-", "")
afterTomorrow = str(today + oneday + oneday).replace("-", "")
todayZero = int(time.mktime(today.timetuple()))
today = str(today).replace("-", "")
for i in range(300000):
upAxisId = "uxi" + str(device_no)
axisVarietyId = "axi" + str(device_no)
varietyId = "vi" + str(device_no)
axisNum = "axn" + str(device_no)
try:
conn.hset('mykey_prefix' + str(device_no), "machineId", str(machineId))
conn.hset('mykey_prefix' + str(device_no), "machineNum", str(machineId))
conn.hset('mykey_prefix' + str(device_no), "factoryId", factory_no)
conn.hset('mykey_prefix' + str(device_no), "groupId", "group_id")
conn.hset('mykey_prefix' + str(device_no), "groupName", "groupName11")
conn.hset('mykey_prefix' + str(device_no), "workshopId", "workshopId11")
conn.hset('mykey_prefix' + str(device_no), "workshopName", "workshopName11")
conn.hset('mykey_prefix' + str(device_no), "source", source)
conn.hset('mykey_prefix' + str(device_no), "errorTimeLimit", str(20))
conn.expire('mykey_prefix' + str(device_no), 864000) # 設定10天過期時間
conn.hset('mykey_prefix' + str(device_no), "axisInfo", json.dumps(axisInfo))
conn.hset('mykey_another_prefix:' + today, str(machineId), json.dumps(fbfcalue))
conn.hset('mykey_another_prefix:' + tomorrow, str(machineId), json.dumps(fbfcalue2))
conn.hset('mykey_another_prefix:' + afterTomorrow, str(machineId), json.dumps(fbfcalue3))
conn.hset('mykey_another_prefix1:' + today, str(machineId), json.dumps(fbfcalue))
conn.hset('mykey_another_prefix1:' + tomorrow, str(machineId), json.dumps(fbfcalue2))
conn.hset('mykey_another_prefix1:' + afterTomorrow, str(machineId), json.dumps(fbfcalue3))
conn.expire('mykey_another_prefix:' + today, 259200) # 3天
conn.expire('mykey_another_prefix:' + tomorrow, 259200)
conn.expire('mykey_another_prefix:' + afterTomorrow, 259200)
conn.expire('mykey_another_prefix1:' + today, 259200)
conn.expire('mykey_another_prefix1:' + tomorrow, 259200)
conn.expire('mykey_another_prefix1:' + afterTomorrow, 259200)
conn.hset('fy:be:de:ma', str(device_no), str(machineId))
conn.expire('fy:be:de:ma', 864000)
machineId = int(machineId) + int(1)
device_no = int(device_no) + int(1)
except Exception as e:
print("設定異常,錯誤資訊:", e)
2.使用pipeline代替每次設定一個key就請求一次
##方法很簡單,只需要兩處小小的改動
使用pipeline
效果非常明顯,已經從365秒變成了126秒,一下子就減少了239秒,將近4約分鐘!
3.使用pipeline + hmset
把同一個key對應的field和value組裝成字典,通過hmset一次性搞定
用了hmset之後,再次壓縮時間,126變成98,耗時縮小了28秒,將近半分鐘
為了進一步壓縮時間,使用golang
實現了一遍,效能很強勁
從python的98秒變成了7.5秒,整整提升了13倍! 是最開始的365秒的48倍!!!
func setDevice() {
var deviceNo string
var deviceInfo map[string]interface{}
// 獲取reids管道
pipe := rdb.Pipeline()
defer pipe.Exec(ctx1)
for i := 0; i < len(devices); i++ {
device := devices[i]
for k, v := range device {
deviceNo = k
deviceInfo = v
}
deviceKey := fmt.Sprintf("%s:%s", deviceInfoKey, deviceNo)
machineId := deviceInfo["machineId"].(string)
// 設定排班資訊
shiftInfo, _ := json.Marshal(shiftToday)
pipe.HSetNX(ctx1, fystTodayKey, machineId, shiftInfo)
pipe.Expire(ctx1, fystTodayKey, time.Hour*24)
pipe.HSetNX(ctx1, fymstTodayKey, machineId, shiftInfo)
pipe.Expire(ctx1, fymstTodayKey, time.Hour*24)
// hmset 代替hset,一次性寫入map
pipe.HMSet(ctx1, deviceKey, deviceInfo).Err()
pipe.Expire(ctx1, deviceKey, time.Hour*72)
if i%1000 == 0 && i >= 1000 {
failCmd, err1 := pipe.Exec(ctx1)
log.Printf("正在設定第%d個採集器 \n", i)
if err1 != nil {
countFail += len(failCmd)
}
}
}
}
4.總結
- 批量寫入時,使用pipeline可以大幅度提升效能
- key相同的field和value,可以用hmset代替hset,也能很好的提升效能
- 操作大量資料時,使用
golang
來代替python
是很棒的選擇
相關文章
- ACCESS大批量資料寫入之效能提升方案
- Redis資料匯入工具優化過程總結Redis優化
- SQLite 3.8.7 大量優化,效能提升 50% 以上SQLite優化
- 實時資料併發寫入 Redis 優化Redis優化
- MySQL 批量匯入資料優化MySql優化
- Java:匯出Excel大批量資料的優化過程JavaExcel優化
- 記一次提升18倍的效能優化優化
- ES寫入效能優化優化
- 小程式redux效能優化,提升三倍渲染速度Redux優化
- 3倍+提升,高德地圖極致效能優化之路地圖優化
- oracle 寫入資料的過程Oracle
- OPPO萬億級資料庫MongoDB叢集效能數十倍提升優化實踐資料庫MongoDB優化
- 40+倍提升,詳解 JuiceFS 後設資料備份恢復效能優化之路UI優化
- hbase大規模資料寫入的優化歷程優化
- Redis批量匯入文字資料Redis
- insert優化(nologging方式提升17倍效能)優化
- kafka connect,將資料批量寫到hdfs完整過程Kafka
- MySQL資料寫入過程介紹MySql
- Golang pprof 效能調優實戰,效能提升 3 倍!Golang
- 效能優化的過程學習優化
- iOS效能優化過程淺析iOS優化
- SQLServer效能優化之 nolock,大幅提升資料庫查詢效能SQLServer優化資料庫
- Redis 效能優化Redis優化
- MySQL的寫入資料儲存過程MySql儲存過程
- 高頻寫入redis場景優化Redis優化
- 【效能優化實踐】優化打包策略提升頁面載入速度優化
- Redis In Action 筆記(四):資料安全和效能優化Redis筆記優化
- 批量插入資料的儲存過程儲存過程
- 【效能優化】ORACLE資料庫效能優化概述優化Oracle資料庫
- MySQL大量資料入庫的效能比較MySql
- 瀏覽器渲染過程與效能優化瀏覽器優化
- 一次效能優化調整過程.優化
- Java 效能優化之——效能優化的過程方法與求職面經總結Java優化求職
- RangeBitmap提升Java流資料過濾效能Java
- 資料庫效能優化資料庫優化
- Web效能優化系列 – 通過提前獲取DNS來提升網頁載入速度Web優化DNS網頁
- 前端效能優化之http請求的過程前端優化HTTP
- MSSQL資料批量插入優化詳細SQL優化