redis数据类型描述+为什么耗内存+为什么容易崩溃

1. 数据类型: string, list, hash, set, sorted set.
2. 数据内存描述:
redis数据类型描述+为什么耗内存+为什么容易崩溃_第1张图片
redisObject对象表示所有的key和value。redisObject主要的信息如图表示:type表示一个value对象具体是何种数据类型,encoding是不同数据类型在redis内部的存储方式。
VM字段只有打开了redis虚拟内存功能后,此字段才会真正的非配内存,该功能默认是关闭的。
redisObject表示方式比较浪费内存,但这些内存管理成本也是为了给reids不同数据类型提供统一的管理接口。
3. 内存优化与参数:
a) 关闭VM选项——vm-enabled 为no:这个功能是redis存储超出物理内存数据的一种数据在内存与磁盘患处的一个持久化策略,但其内存管理成本也非常高,更重要的是此持久化策略并不成熟。
b) 设置reids.conf中的maxmemory选项,该选项告诉reids使用了多少物理内存后就开始拒绝后续的写入请求,该参数保护了redis不会因为使用过多物理内存而导致swap,最终严重影响性能,甚至崩溃。
c) list-max-ziplist-entries  list-max-ziplist-value等参数的设置。
4. redis持久化机制:
a) 定时快照方式snapshot:redis内部一个定时器事件,每个固定时间去检查当前数据发生的改变次数与时间是否满足配置的持久化触发条件,如果满足就通过操作系统的fork调用创建一个子进程,子进程默认与父进程共享相同的地址空间,这时就可以通过子进程来遍历整个内存来进行存储操作,主进程则仍然可以提供服务。当然有些操作时,操作系统按照内存页为单位进行copy-on-write,保证父子进程之间不会互相影响。
这种方法的主要缺点:重启会丢失上次快照与重启之间的所有数据。
b) 基于语句追加文件方式aof:类似mysql的基于语句的 binlog方式,即每条会使redis内存数据发生改变的命令都会追加到一个log文件中,也就是这个log文件就是redis的持久化数据。
主要缺点是:导致log文件体积过大,当系统重启恢复数据时加载数据非常慢,几十G数据可能需要几个小时才能加载完成。读写性能也会下降。
c) 虚拟内存:用户空间的数据换入换出的策略,此种方式在实现的效果上比较差。代码复杂,重启慢,复制慢。作者已经放弃。
d) diskstore内存:放弃了vm方式后选择的一种方式,是一种传统的B-tree方式,目前在实验阶段。
a)和b)是基于全部数据都在内存中,即小数据量下提供的磁盘落地功能,c) 和d)在实验阶段,并且vm方式基本已经被废弃,实际生产环境中只有前两种方式。所以 redis目前只能作为小数据量存储(全部数据在内存中),海量数据存储方面不是reids擅长的领域。
5. 磁盘IO问题:
redis持久化使用了buffer io造成redis不稳定甚至崩溃。
buffer io指持久化文件的写入和读取操作都会使用物理内存的page cache,而大多数数据库系统会使用Direct IO来绕过这层cache并自行维护一个数据的cache。当redis持久化文件过大(尤其是快照文件),并对其进行读写时,磁盘文件中的数据都会被加载到物理内存中作为操作系统对该文件的一层cache,而这层cache的数据与redis内存中管理的数据实际是重复存储的,虽然内核在物理内存紧张时会做page cache的剔除工作,但内核很可能认为某块page cache更重要,而你的进程开始swap,这时你的系统就会开始出现不稳定或者崩溃了。当物理内存使用超过3/5时就开始危险了。

下图是Redis在读取或者写入快照文件dump.rdb后的内存数据图:

redis数据类型描述+为什么耗内存+为什么容易崩溃_第2张图片

总结:
  1. 根据业务需要选择合适的数据类型,并为不同的应用场景设置相应的紧凑存储参数。
  2. 当业务场景不需要数据持久化时,关闭所有的持久化方式可以获得最佳的性能以及最大的内存使用量。
  3. 如果需要使用持久化,根据是否可以容忍重启丢失部分数据在快照方式与语句追加方式之间选择其一,不要使用虚拟内存以及diskstore方式。
  4. 不要让你的Redis所在机器物理内存使用超过实际内存总量的3/5。

你可能感兴趣的:(存储)