减少 Redis 中的内存使用
Short structures 使用更短的结构
Redis stores a serialized version of the data, which must be decoded for every read, partially re-encoded for every write, and may require moving data around in memory.
Sharded structures 分片的数据结构
Packing bits and bytes 更紧凑的位和字节
社交网站的所有用户都有位置信息,如何在 Redis 中使用更少的内存存储每一个用户的未知信息?而且要能够方便的进行聚合计算
假设用户的 ID 都是连续的数组,且只存储国家,区域/州/省信息两级信息;并使用 ISO3 中的国家代码,如下:
1 | # 国家代码 |
最直接的方法是直接以字符串的方式直接存储国家和州代码,每个国家代码至少 3 个字节,州信息至少 2 个字节;
解决方法:以分片的形式存储定长大小的数据
实际存储的时候,并不存储实际的国家和州代码,而只存储其在 “表”(数组) 中的索引代表的字符,这样,只用两个字节就可以存储国家和州信息了(数组长度不会超过单个字节的十进制数字表示)。
1 | def get_code(country, state): |
Redis 中 STRING 结构的值大小限制为 512 MB, 所有用户的信息存储在单个 STRING 的值中必然不可取, 通过进行分片,限制每个分片最多存储 2 百万个用户的位置信息,单个 Key 的值占用大概在 2 MB. 通过 SETRANGE
, GETRANGE
命令就可以更新和获取单个用户的位置信息
这里没有限制分片的个数,只限制了每个分片的大小,考虑的是用户 ID 都是有序的,通过 ID 和每个分片的大小,就可以计算每个 ID 所属的分片, 以及分片内的偏移量;为了知道当前一共由多少分片,就要存储当前的最大用户 ID.
这样进行存储,要对这些信息进行聚合计算,比如统计所有用户的国家,州分布,就比较容易,遍历所有分片进行统计,当然由于每个分片 STRING 的值比较大,需要分批多次去读取,而不能直接去读取,会阻塞其它客户端
这里虽然使用的是多个字节存储的,但是某些情况下,GETBIT
, SETBIT
命令来获取和设置单个二进制位可能更高效,更节省空间。存储 Boolean 型?
存储数据在 Redis 中的方式,会极大地影响所使用地内存。