一、降低内存的好处:降低redis的内存占用有助于减少创建快照和加载快照所需的时间、提升载入AOF文件和重写AOF文件时的效率、缩短从服务器进行同步所需的时间,并且能让redis存储更多的数据而无需添加额外的硬件。
二、降低内存的三个方法:短结构、分片结构、打包存储二进制位的字节。
三、短结构:redis为列表、集合、散列和有序集合提供了一组配置选项,这些选项可以让redis以更节约空间的方式存储长度较短的结构。
(一)压缩列表:在列表、散列和有序集合的长度较短或者体积较小的时候,redis可以选择使用一种名为压缩列表的紧凑存储方式来存储这些结构;压缩列表是列表、散列和有序集合者3种不同类型的对象的一种非结构化表示;压缩列表会以序列化的方式存储数据,这些序列化数据每次被读取的时候都要进行解码,每次被写入的时候也要进行局部的重新编码,并且可能需要对内存里买呢的数据进行移动。
压缩列表结构:压缩列表是由节点组成的序列,每个节点都由两个长度值和一个字符串组成。第一个长度值记录的是前一个节点的长度,这个长度值将被用于对压缩列表进行从后向前的遍历,第二个长度值记录了当前节点的长度,而位于节点最后的则是被存储的字符串值。
配置选项代码:
list-max-ziplist-entries 512 //列表结构的压缩列表配置
list-max-ziplist-value 64
hash-max-ziplist-entries 512 //散列结构的压缩配置
hash-max-ziplist-value 64
zset-max-ziplist-entries 128 //有序集合的压缩配置
zset-max-ziplist-value 64
其中:entries选项说名列表、散列和有序集合在被编码为压缩列表的情况下,允许包含的最大元素数量;而value选项则说明了压缩列表每个节点的最大体积是多少个字节。当这些选项设置的限制条件中的任意一个被突破的时候,redis就会将相应的列表、散列或是有序集合从压缩列表编码转换为其他结构。
(二)整数集合:如果整数包含的所有成员都可以被解释为十进制整数,而这些整数又处于平台的有符号整数范围之内,并且集合成员的数量又足够少的话,那么redis就会以有序整数数组的方式存储集合,这种存储方式又被称为整数集合。
配置选项代码:
set-max-intset-entries 512 //集合使用整数集合表示俄限制条件
缺点:对一个压缩列表表示的对象的其中一部分进行读取或者更新,可能会需要对整个压缩列表进行解码,甚至还需要对内存里面的数据进行移动,因此读写一个长度较大的压缩列表可能会给性能带来负面的影响;数据集合在执行插入操作或者删除操作时需要对数据进行移动。
解决方案:一般将压缩列表的长度限制在1024个元素之内,并且每个元素的体积不能超过64字节,可以同时兼顾低内存占用和高性能者两方面优点。
四、分片结构:分片本质上就是基于某些简单的规则将数据划分为更小的部分,然后根据数据所属的部分来决定将数据发送到哪个位置上面;使用这种技术来扩展存储空间并提高自己所能处理的负载量。
(一)分片式散列:对散列进行分片首先需要选择一个方法来对数据进行划分。
public String shardKey(String base, String key, long totalElements, int shardSize) {
long shardId = 0;
if (isDigit(key)) {
shardId = Integer.parseInt(key, 10) / shardSize;
}else{
CRC32 crc = new CRC32();
crc.update(key.getBytes());
long shards = 2 * totalElements / shardSize;
shardId = Math.abs(((int)crc.getValue()) % shards);
}
return base + ':' + shardId;
}
(二)分片集合
public Long shardSadd(
Jedis conn, String base, String member, long totalElements, int shardSize)
{
String shard = shardKey(base, "x" + member, totalElements, shardSize);
return conn.sadd(shard, member);
}