redis内存优化

小集合数据类型的特殊编码

自redis2.2以后, 许多数据类型进行了优化, 可以使用更少的内存空间达到一定的大小. Hashes, Lists, 由整型组成的Sets, 以及Sorted Sets将会被最高节省10倍的内存的方式编码( 平均节省5倍 )
这在用户和API中是完全透明的. 因为这是CPU/内存的平衡, 所以它能够为特殊的编码类型调整元素的最大数量和元素的最大内存大小, 通过redis.conf的指令配置

hash-max-zipmap-entries 64 (hash-max-ziplist-entries for Redis >= 2.6)
hash-max-zipmap-value 512  (hash-max-ziplist-value for Redis >= 2.6)
list-max-ziplist-entries 512
list-max-ziplist-value 64
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
set-max-intset-entries 512

如果特殊的编码值超出了配置的最大值, 那么redis就会自动将特殊的编码转化为普通的编码. 这个操作对于小数据来说非常快速, 但是如果你修改配置为了让特殊编码运用在更大的聚合类型上, 那么你需要测试这些值的转换时间.

使用32位实例

如果redis编译成32位, 那么每一个key将使用更少的内存, 因为32位系统的指针比较小, 但是32位的实例只有最大4GB的内存使用. 为了编译redis成32位, 可以使用命令make 32bit. RDB和AOF文件都兼容32位和64位, 所以你可以在32位和64位之间来回切换, 而不会有问题.

位和字节级别操作

redis2.2 引进了新的bit和byte级别的操作: GETRANGE, SETRANGE, GETBIT 和 SETBIT. 使用这些命令, 你可以把string类型大作随机访问的数组.
举个例子, 如果你的应用使用递增的整型数作为用户的唯一标识, 那么你可以使用bitmap保存用户的性别, 用bit( 1 )表示女, 0 表示男. 假如有8个用户

100110100

以上8位即可表示8个用户的性别, 从左往右看, 分别是user_id=7到user_id=0的用户, 通过下面代码修改用户性别

SETBIT users:sex user_id 1 ( 表示女 )
SETBIT users:sex user_id 0 ( 表示男 )  

即使有一亿个用户, 它们的性别数据也只需要占用12MB内存就可以了. 你也可以使用GETRANGE 和 SETRANGE 将用户信息存储为字节.

尽可能使用hashes

小的hashes能够被编码为占用非常小的内存空间, 所以你尽可能让你的数据用hashes来存储. 举个例子, 如果你把用户信息保存在redis中, 那么不要使用不同的key去分别存储name, password, email等用户数据, 而应该使用单个hash去处理这些属性.

使用hashes提取出内存高效的键值对存储

基本上redis能够模拟一个键值对的存储, 但值只能是string类型, 而且内存效率比redis简单的key和memcached都更低.
事实上, 多个key比包含多个属性的单个哈希key更耗内存, 理论上我们为了确保能在常数时间内( 总所周知是O( 1 ) )完成查询操作, 我们需要一种在大部分场景都能在常数时间执行的数据结构, 比如 hash table.
但是很多时候hashes只包含少量的属性. 当hashes很小的时候, 我们使用O( N )的数据结构去编码它, 例如拥有长前缀键值对的线性数组. 因为我们只在N很小的时候这么做, 所以HGET 和 HSET 的消耗时间还是O( 1 ): 一旦hashes元素的数量快速增长, 那么我们就会将它转化为真正的hash table( 这个数量限制也可以在redis.conf进行配置 ).
如果单单从时间复杂度和固定时间的角度去看, 这不是一个好的方式. 但是运用CPU的缓存, 键值对的线性数组能够很好的完成工作.
然而hash的属性和值不能代表所有redis对象, hash属性不能关联一个过期时间( key可以, 但属性不行 ), 以及只能包含一个string. 但是这是没有问题的, 在设计hash数据类型的时候这都是有原因的. ( 我们相信简洁重要性多与功能, 所以嵌套数据结构是不允许的, 以及单个属性设置过期时间也是不允许的. )
所以hashes是内存高效的. 这是非常有用的, 当使用hashes表示一些对象和模拟一些有多组关联属性的问题. 但是如果我们有一个简单的键值对场景怎么办?
想象我们需要使用redis作为许多小对象的缓存, 可能是JSON对象, 小的HTML碎片, 简单的key->boolean值等等. 基本上都是string->string映射为小的键值对

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值