Redis字符串可能是最常用(和滥用)的Redis数据结构。它的主要优势之一是二进制安全——这意味着你可以在Redis中保存任何类型的二进制数据。但在实际当中,大多数Redis用户会将对象序列化为JSON字符串,再将它们存储在Redis中。
你可能会问这有什么问题呢?
- JSON序列化/反序列化非常低效和耗CPU
- 你最终会使用更多的存储空间(这在Redis中是昂贵的,因为它是一个内存数据库)
- 这增加了整体服务延迟,却没有任何实际好处。
在Redis中使用JSON存储数据会增加延迟和资源使用,但不会带来任何真正的好处。
您可以使用的另一个“简单”优化方法是压缩。这将取决于实际应用场景,因为它将在占用空间、延迟和CPU使用之间进行权衡。
像ZSTD或LZ4这样的算法可以获得最小的CPU开销,从而很好地节省了存储空间。
下面的实验显示了从JSON转换到二进制格式(如MessagePack)所获得的优化。这些图表包括序列化/反序列化时间。我们还可以看到,通过使用压缩,我们可以增加一些延迟为代价来节省一些存储/内存。
使用具有不同属性的随机“JSON”对象
使用具有不同属性的随机“JSON”对象
虽然前面的图表显示了LZ4可以很好地处理复杂的JSON对象(压缩比)。当我们需要压缩浮点数数组时,我们可以在下一个图表中看到ZSTD的优势。
这里我使用不同大小的数组运行基准测试。
使用一个小浮点型数组
使用一个小的浮动数组
使用大浮点型数组
使用大浮点型数组
正如您所看到的,只需从JSON切换到MessagePack,您就可以减少3倍以上的延迟,而且没有任何真正的副作用!
以下是使用python来实现redis的字符串的set和get操作:
import msgpack
import redis
import json
data = {} # normal python dictionary with any values
r = redis.Redis(host='REDIS_HOST', port=6379, db=0)
# using json
r.set('foo_json', json.dumps(data))
json.loads(r.get('foo_json').decode('utf-8'))
# using msgpack
r.set('foo_msgpack', msgpack.packb(data))
msgpack.unpackb(r.get('foo_msgpack'))
MessagePack也有golang的库:https://github.com/vmihailenco/msgpack