Redis是一个开源的高性能的key-value存储系统。具备如下特色:java
一、Redis支持数据的持久化,能够将内存中的数据保持在磁盘中,重启的时候能够再次加载进行使用。mysql
二、Redis不只仅支持简单的key-value类型的数据,同时还提供list,set,sorted set,hash等数据结构的存储。redis
三、Redis支持数据的备份,即master-slave模式的数据备份。sql
Redis优点:数据库
一、性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。缓存
二、丰富的数据类型 – Redis支持二进制案例的 String, List, Hash, Set 及 Sorted Set 数据类型操做。安全
三、原子 – Redis的全部操做都是原子性的,同时Redis还支持对几个操做全并后的原子性执行。服务器
四、丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过时等等特性网络
string、hash、list、set、sorted set数据结构
首先 Redis 内部使用一个 redisObject 对象来表示全部的 key 和 value,redisObject 最主要的信息如上图所示:type 表明一个 value 对象具体是何种数据类型,encoding 是不一样数据类型在 redis 内部的存储方式,好比:type=string 表明 value 存储的是一个普通字符串,那么对应的 encoding 能够是 raw 或者是 int,若是是 int 则表明实际 redis 内部是按数值型类存储和表示这个字符串的,固然前提是这个字符串自己能够用数值表示,好比:”123″ “456”这样的字符串。
一、首先最重要的一点是不要开启 Redis 的 VM 选项,即虚拟内存功能,这个原本是做为 Redis 存储超出物理内存数据的一种数据在内存与磁盘换入换出的一个持久化策略,可是其内存管理成本也很是的高,而且咱们后续会分析此种持久化策略并不成熟,因此要关闭 VM 功能,请检查你的 redis.conf 文件中 vm-enabled 为 no。
二、其次最好设置下 redis.conf 中的 maxmemory 选项,该选项是告诉 Redis 当使用了多少物理内存后就开始拒绝后续的写入请求,该参数能很好的保护好你的 Redis 不会由于使用了过多的物理内存而致使 swap,最终严重影响性能甚至崩溃。
三、Redis 为不一样数据类型分别提供了一组参数来控制内存使用,咱们在前面详细分析过 Redis Hash 是 value 内部为一个 HashMap,若是该 Map 的成员数比较少,则会采用相似一维线性的紧凑格式来存储该 Map,即省去了大量指针的内存开销,这个参数控制对应在 redis.conf 配置文件中下面2项:
hash-max-zipmap-entries
64
hash-max-zipmap-value
512
hash-max-zipmap-entries
|
含义是当 value 这个 Map 内部不超过多少个成员时会采用线性紧凑格式存储,默认是64,即 value 内部有64个如下的成员就是使用线性紧凑存储,超过该值自动转成真正的 HashMap。
hash-max-zipmap-value 含义是当 value 这个 Map 内部的每一个成员值长度不超过多少字节就会采用线性紧凑存储来节省空间。
以上2个条件任意一个条件超过设置值都会转换成真正的 HashMap,也就不会再节省内存了,那么这个值是否是设置的越大越好呢,答案固然是否认的,HashMap 的优点就是查找和操做的时间复杂度都是 O(1) 的,而放弃 Hash 采用一维存储则是 O(n) 的时间复杂度,若是成员数量不多,则影响不大,不然会严重影响性能,因此要权衡好这个值的设置,整体上仍是最根本的时间成本和空间成本上的权衡。
Redis提供了下面几种淘汰策略供用户选择,其中默认的策略为noeviction策略:
redis是一个支持持久化的内存数据库,也就是说redis须要常常将内存中的数据同步到磁盘来保证持久化。
redis支持两种持久化方式,一种是 Snapshotting(快照)也是默认方式,另外一种是Append-only file(aof)的方式。
快照是默认的持久化方式。这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。能够经过配置设置自动作快照持久化的方式。咱们能够配置redis在n秒内若是超过m个key被修改就自动作快照。也能够命令行的方式让redis进行snapshotting。
快照生成过程大体以下:
同时snapshotting也有不足的,由于两次快照操做之间是有时间间隔的,一旦数据库出现问题,那么快照文件中保存的数据并非全新的,从上次快照文件生成到Redis停机这段时间的数据所有丢掉了。若是业务对数据准确性要求极高的话,就得采用aof持久化机制了。
比快照方式有更好的持久化性,是因为在使用aof持久化方式时,redis会将每个收到的写命令都经过write函数追加到文件中(默认是 appendonly.aof)。当redis重启时会经过从新执行文件中保存的写命令来在内存中重建整个数据库的内容。固然因为os会在内核中缓存 write作的修改,因此可能不是当即写到磁盘上。这样aof方式的持久化也仍是有可能会丢失部分修改。不过咱们能够经过配置文件告诉redis咱们想要经过fsync函数强制os写入到磁盘的时机。有三种方式以下(默认是:每秒fsync一次):
一、appendonly yes //启用aof持久化方式
二、# appendfsync always //每次收到写命令就当即强制写入磁盘,最慢的,可是保证彻底的持久化,不推荐使用
三、appendfsync everysec //每秒钟强制写入磁盘一次,在性能和持久化方面作了很好的折中,推荐
四、# appendfsync no //彻底依赖os,性能最好,持久化没保证
aof 的方式也同时带来了另外一个问题。持久化文件会变的愈来愈大。例如咱们调用incr test命令100次,文件中必须保存所有的100条命令,其实有99条都是多余的。由于要恢复数据库的状态其实文件中保存一条set test 100就够了。为了压缩aof的持久化文件。redis提供了bgrewriteaof命令。收到此命令redis将使用与快照相似的方式将内存中的数据 以命令的方式保存到临时文件中,最后替换原来的文件。
bgrewriteaof命令执行过程以下:
这两种持久化方式有各自的特色,快照相对性能影响不大,但一旦崩溃,数据量丢失较大,而aof数据安全性较高,但性能影响较大,这就得根据业务特色自行选择了。
Redis能够说是基于单线程模型的,由于对于客户端的全部读写请求的处理,都由一个主线程串行地处理,所以多个客户端同时对一个键进行写操做不会有并发问题,可是除了客户端读写请求以外还有一些比较耗时的操做,如持久化RDB文件,持久化AOF文件等等,这些操做不能放在主线程里面处理,所以Redis会在适当的时候fork子进程来异步的处理这种任务。除了这些,Redis还有一组异步任务处理线程,用于处理不须要主线程同步处理的工做,整体上Redis的线程体系结构大体以下图:
Redis的主从复制功能很是强大,一个master能够拥有多个slave,而一个slave又能够拥有多个slave,如此下去,造成了强大的多级服务器集群架构。下面是关于redis主从复制的一些特色:
1.master能够有多个slave
2.除了多个slave连到相同的master外,slave也能够链接其余slave造成图状结构
3.主从复制不会阻塞master。也就是说当一个或多个slave与master进行初次同步数据时,master能够继续处理client发来的请求。相反slave在初次同步数据时则会阻塞不能处理client的请求。
4.主从复制能够用来提升系统的可伸缩性,咱们能够用多个slave 专门用于client的读请求,好比sort操做可使用slave来处理。也能够用来作简单的数据冗余
5.能够在master禁用数据持久化,只须要注释掉master 配置文件中的全部save配置,而后只在slave上配置数据持久化。
下面介绍下主从复制的过程
当设置好slave服务器后,slave会创建和master的链接,而后发送sync命令。不管是第一次同步创建的链接仍是链接断开后的从新连 接,master都会启动一个后台进程,将数据库快照保存到文件中,同时master主进程会开始收集新的写命令并缓存起来。后台进程完成写文件 后,master就发送文件给slave,slave将文件保存到磁盘上,而后加载到内存恢复数据库快照到slave上。接着master就会把缓存的命 令转发给slave。并且后续master收到的写命令都会经过开始创建的链接发送给slave。从master到slave的同步数据的命令和从 client发送的命令使用相同的协议格式。当master和slave的链接断开时slave能够自动从新创建链接。若是master同时收到多个 slave发来的同步链接命令,只会使用启动一个进程来写数据库镜像,而后发送给全部slave。
redis的主从复制策略是经过其持久化的rdb文件来实现的,其过程是先dump出rdb文件,将rdb文件全量传输给slave,而后再将dump后的操做实时同步到slave中。
从以上的复制过程当中能够发现,Slave从库在链接Master主库时,Master会进行内存快照,而后把整个快照文件发给Slave,也就是没有象MySQL那样有复制位置的概念,即无增量复制,若是一个master链接多个slave,就会比较影响master性能了。
Redis事务一般会使用MULTI,EXEC,WATCH等命令来完成,redis实现事务实现的机制与常见的关系型数据库有很大的却别,好比redis的事务不支持回滚,事务执行时会阻塞其它客户端的请求执行。
Redis事务从开始到结束一般会经过三个阶段:一、事务开始,二、命令入队,三、命令执行。
redis > MULTI
OK
redis > SET
"username"
"huating"
QUEUED
redis > SET
"password"
161616
QUEUED
redis > GET
"username"
redis > EXEC
1
) ok
2
)
"huating"
3
)
"huating"
|
与事务相关的状态flag
#define REDIS_MULTI (
1
<<
3
)
#define REDIS_DIRTY_EXEC (
1
<<
12
)
#define REDIS_DIRTY_CAS (
1
<<
5
)
|
一、延迟失效机制:也叫消极失效机制,延迟失效机制即当客户端请求操做某个key的时候,Redis会对客户端请求操做的key进行有效期检查,若是key过时才进行相应的处理
二、主动失效机制:也叫积极失效机制,即服务端定时的去检查失效的缓存,若是失效则进行相应的操做。
|
redis
|
memcached
|
---|---|---|
|
redis
|
memcached
|
数据类型 | 支持多种数据类型 | 只支持简单的k-v |
数据持久化支持 | 支持数据持久化 | 全内存模式 |
数据一致性 | 提供了事务的功能,能够保证一串 命令的原子性,中间不会被任何操做打断 | 提供了cas命令,能够保证多个并发访问操做同一份数据的一致性问题 |
集群 | 服务端分布式 | 客户端分布式 |
内存管理 | 实时分配内存 | 预分配内存 |