您的位置:首页 > 数据库 > Redis

Redis内存使用优化

2016-10-07 17:37 169 查看
Redis常用数据类型有5种:String 、Hash、 List 、Set 、Sorted set

Redis内部内存管理是如何描述这些不同数据类型的呢?



Redis内部使用一个redisObject对象表示所有的key和value,RedisObject中包括最主要的信息:type表示一个value对象具体是何种数据类型,encoding是不同数据类型在redis内部的存储方式,type=string代表redis存储的是一个普通字符串,那么对应encoding可以是raw或int,如果int代表实际redis内部是按照数值类型存储和表示这个字符串的,那么这个字符串本事是可以用数值表示,例如“123”这样的字符串。

vm字段表示只有打开了Redis虚拟内存功能,此字段才会真正分配内存。

先来说一下五种数据类型的使用和内部实现方式:

String :在redis内部存储默认就是一个字符串,被redisObject所引用。

Hash:例如存储一个对象包含姓名、年龄、生日等。如果是普通key-value,有两种存储方式:

第一种将ID作为key,其他信息封装成一个对象以序列化方式存储,但是增加了序列化/反序列化开销,并在修改其中一项信息时,需要把整个对象取回,同时要防止并发。



第二种思这个对象有多少成员就存成多少个key-value对,内存浪费。



Redis提供的Hash很好解决了问题,Redis的Hash实际是内部存储的Value为一个HashMap,并提供了直接存取这个Map成员的接口。



key仍然是用户id,value是一个map,map的key(redis称内部Map的key为field)是成员的属性名,value是属性值,

Redis提供了接口(hgetall)可以直接取到全部属性数据,但是如果内部map成员比较多,因为redis是单线程,遍历就会比较耗时。

实现方式:RedisHash对应的value内部实际上是一个HashMap,实际上会有2中不同实现,如果Hash成员比较少时,Redis会节省内存次用类似一堆数组的方式来紧凑存储,不会采用真正的Hashmap结构,对应的value redisObject的encoding 为zipmap,当成员数量增大时会自动转成真正的Hashmap,此时encoding为ht。

List:实现方式:redis list为一个双向链表,既可以反向查找和遍历,不过带来了部分额外的内存开销。

Set:Redis set对外提供的功能与list类似是一个列表的功能。不过set是可以自动排重的。

实现方式:set实现是一个value永远为null的hashmap,实际就是通过计算hash的方式来快速排重的。

Sorted set:与set类似,不过sorted set是自动有序的。

实现方式:使用Hashmap和跳跃表(SkipList)来保证数据的存储和有序,Hashmap里放的是成员到score的映射,而跳跃表里方的是所有的成员,排序是依据hashmap中的score。

Redis持久化机制:

由于Redis支持丰富的内存数据结构类型,如何把这些负责内存组织持久化到磁盘是一个难题,所以Redis持久化与传统数据库有较多差别。redis支持4种持久化方式。分别是:

定时快照方式(snapshot)、基于语句追加文件的方式、虚拟内存、Diskstore方式

前两种是基于全部数据都在内存中,即小数据量下提供磁盘落地功能,后两种是在存储数量超过物理内存时(大数据量时)目前仍在实验阶段。所以redis目前还只能作为小数据量存储(全部数据能够加载在内存中)。

定时快照方式:实际上是Redis内部一个定时器事件,每隔固定时间去检查当前数据发生的改变次数与时间是否满足配置的持久化触发的条件,如果满足则通过操作系统fork一个子进程,这个子进程会默认与父进程共享相同的地址空间,这是子进程就可以遍历整个内存来进行存储操作,主进程依然提供服务,当有写操作时操作系统按照内存页(page)为单位进行copy-on-write保证父子进程之间不会影响。

缺点:定时快照只是一段时间内的内存映像,所以系统重启会丢失上次快照和重启之间所以数据。

基于语句追加方式(aof):类似mysql基于语句的binlog方式,每条会使redis内存数据发生改变的命令都会追加到一个log文件中,也就是这个log文件就是redis的持久化数据。缺点是:log文件可能过大,当系统恢复重启时可能加载数据非常慢。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: