利用spark的分布式优势,一次性批量将7000多万的数据写入到redis中。
# 配置spark接口
import os
import findspark
from pyspark import SparkConf
from pyspark.sql import SparkSession
os.environ["JAVA_HOME"] = "/usr/local/jdk1.8.0_192"
findspark.init("/usr/local/hadoop/spark-2.4.4-bin-hadoop2.6/")
# 设置配置信息
conf = SparkConf()
conf.set("spark.driver.memory", "16g")
conf.set("spark.executor.memory", "16g")
conf.set("spark.driver.maxResultSize","3g")
conf.set("spark.executor.maxResultSize", "3g")
conf.set("spark.ui.showConsoleProgress","false") # 取消进度条显示
spark = SparkSession.builder.appName("local_redis_spark").master("local[*]").enableHiveSupport().config(conf=conf).getOrCreate()
spark.sparkContext.setLogLevel("ERROR") # 提升日志级别
import redis
# 初始化一个全局函数来获取Redis连接池
def get_redis_connection_pool():
# 配置redis参数
host='127.0.0.1' # 替换为redis的服务地址即可
port=6379
password='123456' # 密码
db=1 # db库如果不设置 默认为0
max_connections=10 # 设置最大连接数
redis_pool = redis.ConnectionPool(host=host, port=port, db=db, password=password, max_connections=max_connections)
return redis_pool
# 清空旧数据
with redis.Redis(connection_pool=get_redis_connection_pool()) as r:
r.flushdb() # 清空当前库的所有数据 而flushall()则情况所有库数据
%%time
# 并行处理函数serv_id
def servid_pfun(sdf_data):
# 定义redis写入函数 以连接池的方式获取链接 及时释放
def write_to_redis(data_dict):
with redis.Redis(connection_pool=get_redis_connection_pool()) as r:
r.mset(data_dict)
# 构建一个空字典 批量写入
dat = {}
for rw in sdf_data:
dat[rw.serv_id] = str((rw.r_inst_id, rw.avg_value))
# 批量写入
write_to_redis(dat)
# 并行处理函数one_id
def oneid_pfun(sdf_data):
# 定义redis写入函数 以连接池的方式获取链接 及时释放
def write_to_redis(data_dict):
with redis.Redis(connection_pool=get_redis_connection_pool()) as r:
r.mset(data_dict)
# 构建一个空字典 批量写入
dat = {}
for rw in sdf_data:
dat[rw.r_inst_id] = str((rw.offer_list,rw.filter_prod_offer_inst_list,rw.fuka_serv_offer_list,rw.filter_list,rw.new_serv_id))
# 批量写入
write_to_redis(dat)
# 加载缓存数据
oneid_sdf = spark.sql("""select * from database.table1""")
servid_sdf = spark.sql("""select * from database.table2""")
# 设置分区数 如果批量写入的内存大小以及最大链接数有限制
# servid_num_parts = 50000
# oneid_num_parts = 10000
# 使用repartition方法进行重新分区
# servid_sdf_part = servid_sdf.repartition(servid_num_parts)
# oneid_sdf_part = oneid_sdf.repartition(oneid_num_parts)
# 分批写入redis
servid_sdf.foreachPartition(servid_pfun)
print(f"servid字典缓存成功")
oneid_sdf.foreachPartition(oneid_pfun)
print(f"oneid字典缓存成功")
# 关闭spark
spark.stop()
print(f"redis缓存插入成功")
执行时间可能跟资源环境有关,测试整个过程大概只需要5分钟左右,非常快速。