最近遇到一个问题:用python写500W+的数据到redis,时间要花费2小时左右。该如何优化呢?

redis介绍

Redis是REmote DIctionary Server的缩写。对Redis的作用的不同解读决定了你对Redis的使用方式。如果你认为Redis是一个key value store, 那可能会用它来代替MySQL;如果认为它是一个可以持久化的cache, 可能只是用它保存一些频繁访问的临时数据。有一些看法则认为Redis是一个memory database,因为它的高性能都是基于内存操作的基础。另外一些人则认为Redis是一个data structure server,因为Redis支持复杂的数据特性,比如List, Set等。

互联网数据目前基本使用两种方式来存储,关系数据库或者key value( NoSQL)。但是这些互联网业务本身并不属于这两种数据类型,比如用户在社会化平台中的关系,它是一个list,如果要用关系数据库存储就需要转换成一种多行记录的形式,这种形式存在很多冗余数据,每一行需要存储一些重复信息。如果用key value存储则修改和删除比较麻烦,需要将全部数据读出再写入。Redis在内存中设计了各种数据类型,让业务能够高速原子的访问这些数据结构,并且不需要关心持久存储的问题,从架构上解决了前面两种存储需要走一些弯路的问题。

redis数据类型

String

string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。


Python:教你一招,将500W+的数据快速写入redis

Hash

Redis hash 是一个 string 类型的 key 和 value 的映射表,hash 特别适合用于存储对象。


Python:教你一招,将500W+的数据快速写入redis

List

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。


Python:教你一招,将500W+的数据快速写入redis

Set

Redis的Set是string类型的无序集合。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。


Python:教你一招,将500W+的数据快速写入redis

zset

Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。 不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。

redis在推荐系统中的使用

目前我们是把所有模型计算的结果用zset的数据结构写入redis,其中key的设计为:


Python:教你一招,将500W+的数据快速写入redis

value是商品ID和商品分数的字典表。

利用pipeline和多线程写大量数据到redis

Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。这意味着通常情况下一个请求会遵循以下步骤:客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应。

服务端处理命令,并将结果返回给客户端。

Redis 管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。能够有效地提高redis服务的性能。


Python:教你一招,将500W+的数据快速写入redis

500万条数据用pipeline和不用pipeline时间测试


Python:教你一招,将500W+的数据快速写入redis

用pipeline


Python:教你一招,将500W+的数据快速写入redis

可见,500万条数据在使用pipeline比不适用pileline速度快了一倍~是不是可以用多线程让它再快一些呢