Redis特性和性能调优

概要

在分布式里面知足CP (一致性、分区容错性)。redis

性能:对于单纯只有IO操做来讲,单线程能够将速度优点发挥到最大,可是Redis也提供了一些简单的计算功能,好比排序、聚合等,对于这些操做,单线程模型实际会严重影响总体吞吐量,CPU计算过程当中,整个IO调度都是被阻塞住的。数据库

一  Redis和Memcached对比

1:数据类型:Memcached单个key-value大小有限,一个value最大只支持1MB,而Redis最大支持512MB,支持set,list等类型缓存

2:持久性:Memcached只是个内存缓存,对可靠性无要求;而Redis更倾向于内存数据库,所以对对可靠性方面要求比较高、作了数据持久化服务器

3:数据一致性:redis是单线程模型,保证了数据按顺序提交,Redis提供了事务的功能,能够保证一串 命令的原子性,中间不会被任何操做打断。  memcached须要cas保证数据一致性,在高并发下。性能会受到影响,甚至不如redis。架构

二  数据回收策略

相关知识:redis 内存数据集大小上升到必定大小的时候,就会施行数据淘汰策略(回收策略)。redis 提供 6种数据淘汰策略:并发

  1. volatile-lru:从已设置过时时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
  2. volatile-ttl:从已设置过时时间的数据集(server.db[i].expires)中挑选将要过时的数据淘汰
  3. volatile-random:从已设置过时时间的数据集(server.db[i].expires)中任意选择数据淘汰
  4. allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
  5. allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
  6. no-enviction(驱逐):禁止驱逐数据

三  持久化

fork操做都会形成主线程堵塞。这个时候服务是中止的。app

3.1 RDB(redis database)

         rdb为二进制文件,redis在指定的时间内(默认配置3个时间段,1分钟1W次,10分钟10次,15分钟1次),把内存的数据集快照写入到磁盘,恢复的时候是将硬盘中快照文件写入内存。redis 会单独建立(fork)一个子进程去进行持久化,先写入一个临时文件dump.rdb ,待持久化结束了,再替换上次持久化好的文件,整个过程当中,主线程是不须要任何io操做的。(子进程保持数据一致性)。运维手段(上报dump.rdb)运维

         若是须要大规模恢复,且对数据缺失不是很敏感。那么采用RDB,RDB的方式比AOF更加高效,可是最后一次持久化的数据可能丢失。通常作冷数据备份dom

         fork的时候,内存中的数据被克隆了一份,大体2倍的膨胀性须要考虑,当数据集比较大额时候,folk的过程是比较耗时的,可能会致使redis在一些毫秒级不能响应客服端请求分布式

3.2 AOF(append only file)

(若是同时rdb和aof同时存在,先加载aof,error才加载rdb):命令

        redis也会fork一个子进程,以日志的形式记录每次写操做命令。 AOF持久化以日志的形式记录服务器所处理的每个写、删除操做,查询操做不会记录,换句话说,恢复的时候,把文件记录命令所有再执行一遍

       AOF是存放每条写命令的,因此会不断的增大,当大到必定程度时,AOF会作rewrite操做,rewrite操做就是基于当时redis的数据从新构造一个小的AOF文件,而后将大的AOF文件删除。

  1. 对于同一份文件AOF文件比RDB数据快照要大。
  2. AOF开启后支持写的QPS会比RDB支持的写的QPS低,由于AOF通常会配置成每秒fsync操做,每秒的fsync操做仍是很高的
  3. 数据恢复比较慢,不适合作冷备。

四  事务

不保证原子性,部分支持事务,可是能够经过watch实现乐观锁

开启事务-》放入队列-》执行,本质上是一组命令的集合。一个事务中的全部命令都会被序列化,按照顺序串行地执行而不会被其余命令插入。 

原子性:redis事务不能保证原子性,有一个执行失败,其它依被执行,没有回滚

隔离级别:没有数据那些隔离级别概念,队列里面没有提交以前都不会执行,在执行过程当中也不会被其它事务打断。

  1. 若是中途命令(编译)出错。那么所有不执行
  2. 若是是运行时报错,其余依然执行。出错的不执行:字符串+1

一致性问题:

在事务以前有其余执行,那么数据就有误

WATCH (乐观锁)

能够监视一个或多个key,一旦其中有任意一个key被修改,那么事务被打断,都不会被执行,返回失败,可是并不能保证其余客户端不修改监控的值,因此当EXEC命令执行失败以后须要手动从新执行整个事务

伪代码:

exec(WATCH stock:1001);

if(exec(HGET stock:1001 state) == "in stock") {

    exec(MULTI);

    exec(HSET stock:1001 state "sold");

    exec(EXEC);

}

五  集群

软件架构不是越复杂越好,尽可能减小过分设计,咱们用的主从。

5.1 主从复制

info replication —查看集群信息

  1. 只有1Master,能够有Nslaver,并且Slaver也能够有本身的Slaver,因为这种主从的关系决定他们是在配置阶段就要指定他们的上下级关系,而不是Zookeeper那种平行关系是自主推优出来的。
  2. 读写分离,Master只负责写和同步数据给SlaverSlaver承担了被读的任务,因此Slaver的扩容只能提升读效率不能提升写效率。
  3. Slaver先将Master那边获取到的信息压入磁盘,再load进内存,client端是从内存中读取信息的,因此Redis是内存数据库。
  4. 当一个新的Slaver加入到这个集群时,会向主服务器发送一个 SYNC 命令,Master发现新的小弟后将全量数据(全量是rdb、增量是aof文件)发送给新的Slaver,数据量越大性能消耗也就越大,因此尽可能避免在运行时作Slaver的扩容

简单总结下主从模式的设计:

优势:读写分离,经过增长Slaver能够提升并发读的能力。

缺点:Master写能力是瓶颈。

          虽然理论上对Slaver没有限制可是维护Slaver开销总将会变成瓶颈。

          Master的Disk大小也将会成为整个Redis集群存储容量的瓶颈。

Sentinel哨兵模式:

可以后台监控主机是否故障,若是故障了根据投票数自动将从库转换为主库。

5.2  集群分片

哈希Slot [slɒt]:就是分库分表,hash取模

           Redis Cluster中共有16384个hash slot,Redis会计算每一个key的CRC16,将结果与16384取模,来决定该key存储在哪个hash slot中,同时须要指定Redis Cluster中每一个数据分片负责的Slot数。Slot的分配在任什么时候间点均可以进行从新分配。

 

5.3  主从分片

           想扩展并发读就添加Slaver,想扩展并发写就添加Master,想扩容也就是添加Master,任何一个Slaver或者几个Master挂了都不会是灾难性的故障。

简单总结下哈希Slot的优缺点:

缺点:每一个Node承担着互相监听、高并发数据写入、高并发数据读出,工做任务繁重

优势:将Redis的写操做分摊到了多个节点上,提升写的并发能力,扩容简单。

六  缓存穿透、雪崩