数据库缓存
许多web停用都将数据保存到RDBMS(关系型数据库)中,应用服务器中读取数据并在浏览器中显示。但随着数据量增大、访问的集中,就会出现RDBMS的负担加重,数据库响应恶化,网站显示延迟等重大影响。
Memcahe/redis是高性能的分布式内存缓存服务器,通过缓存数据库查询结果,减少数据库访问次数,以提高动态web等应用速度,提高可扩展性。
简而言之:缓存数据库查询结果,加快访问速度,缓解数据库压力。
Nosql
非关系型数据库(not only sql)
- 为弥补关系型数据库的不足
- 以键值方式存储数据
- 缓存数据库
- 产品有redis、memcached、mongoDB
Memcache
特点
- 内置内存存储方式(重启操作系统会导致全部数据消失)
- 简单的key/value存储
- 不互相通信的分布式
缓存原理
- 检查用户请求的数据时缓存中是否存在,若存在直接返回,无需查询数据库。
- 若请求数据在缓存中查询不到,去查询数据库,返回数据,同时把数据存储到缓存中一份。
- 保持缓存的“新鲜性”,每当数据发生变化的时候,要同步更新缓存的信息,确保用户不会在缓存取到旧的数据。
Redis
redis是一个开源的,使用C语言编写的,支持网络交互的,可基于内存也可持久化的key-Value数据库。
官网:redis.io
特点
- 丰富的数据结构
- 支持持久化
- 支持事物(事物:一个完整的动作,要么全部执行,要么什么都没做。)
- 支持主从
安装
从reids.io下载最新版redis-X.Y.Z.tar.gz后解压。然后进入redis-X.Y.Z文件夹make即可。
# wget http://download.redis.io/releases/redis-4.0.9.tar.gz
# tar xzf redis-4.0.9.tar.gz -C /
# cd redis-4.0.9
# make
^若因缺包报错,在安装完缺失的包之后需重新解压新包进行make安装,若没有编译工具需要先安装yum -y install gcc make
启动redis(默认非daemon形式启动)
# ./src/redis-server
指定配置文件启动
# ./src/redis-server ../redis.conf
设置开机启动
1.# mkdir /etc/redis
2.# cp /redis-4.0.9/redis.conf /etc/redis/6379.conf
启动脚本
# vim /etc/init.d/redis
#!/bin/sh
# chkconfig: 2345 10 90
# description: Start and Stop redis
REDISPORT=6379
EXEC=/redis-4.0.9/src/redis-server
#(可更改)
CLIEXEC=/redis-4.0.9/src/redis-cli
#(可更改)
PIDFILE=/var/run/redis_${REDISPORT}.pid
CONF="/etc/redis/${REDISPORT}.conf"
case "$1" in
start)
if [ -f $PIDFILE ]
then
echo "$PIDFILE exists, process is already running or crashed"
else
echo "Starting Redis server..."
$EXEC $CONF & #(增加)
fi
;;
stop)
if [ ! -f $PIDFILE ]
then
echo "$PIDFILE does not exist, process is not running"
else
PID=$(cat $PIDFILE)
echo "Stopping ..."
$CLIEXEC -p $REDISPORT shutdown
while [ -x /proc/${PID} ]
do
echo "Waiting for Redis to shutdown ..."
sleep 1
done
echo "Redis stopped"
fi
;;
restart)
"$0" stop
sleep 3
"$0" start
;;
*)
echo "Please use start or stop as first argument"
;;syst
esac
授权
# chmod 777 /etc/init.d/redis
加入开机启动
# chkconfig --add redis
# chkconfig redis on
# systemctl daemon-reload //重新加载自启动系统
启动方式
# /etc/init.d/redis start 6
# systemctl start redis
端口
默认服务端口为6379
测试
# ./src/redis-cli
127.0.0.1:6379> set name hello
OK
127.0.0.1:6379> get name
"hello"
127.0.0.1:6379> save //保存数据到磁盘
127.0.0.1:6379> shutdown //通过客户端来关闭redis服务端 禁用
数据结构
redis 是一种高级的key:value存储系统,它的value支持五种数据类型:
- 字符串(strings)
- 字符串列表(lists)
- 字符串集合(sets)
- 有序字符串集合(sorted sets)
- 哈希(hashes)
注意:
- key不可太长,尽量不要超过1024字节,这样不仅会小孩内存,而且会降低查找效率。
- key也不要太短,太短的话,key的可读性会降低。
- 在项目中,建议key使用统一的命名格式。
redis持久化
开启持久化功能后,重启redis,数据会自动通过持久化文件恢复。
RDB(默认开启)
在不同的时间点,将redis存储的数据生成快照并存储到磁盘等介质上。RDB方式,是将redis某一时刻的数据持久化到磁盘中,是一种快照式的持久化方法。
redis在进行数据持久化的过程中,会先将数据写入到一个临时文件中,待持久化过程都结束,才会用这个临时文件替换上次持久换文件。这种特性可让我们随时备份文件,因为快照文件总是完整可用的。
特点
周期性
不影响数据写入
RDB会启动子进程,备份所有数据。当前进程继续提供数据读写,当备份完成替换老的备份文件。
高效,一次性还原所有数据
完美性较差
故障点到上一次备份之间的数据无法恢复。
查看RDB开启状态
vim /redis-4.0.9/redis.conf
dbfilename dump.rdb
#dbfilename:持久化数据存储在本地的文件
dir ./
#dir:持久化数据存储在本地的路径,如果是在/redis/redis-3.0.6/src下启动的redis-cli,则数据会存储在当前src目录下
save 900 1
save 300 10
save 60 10000
##snapshot触发的时机,save <seconds> <changes>
##如下为900秒后,至少有一个变更操作,才会snapshot
##对于此值的设置,需要谨慎,评估系统的变更操作密集程度
##可以通过“save “””来关闭snapshot功能
#save时间,以下分别表示更改了1个key时间隔900s进行持久化存储;更改了10个key300s进行存储;更改10000个key60s进行存储。
stop-writes-on-bgsave-error yes
##当snapshot时出现错误无法继续时,是否阻塞客户端“变更操作”,“错误”可能因为磁盘已满/磁盘故障/OS级别异常等
rdbcompression yes
##是否启用rdb文件压缩,默认为“yes”,压缩往往意味着“额外的cpu消耗”,同时也意味这较小的文件尺寸以及较短的网络传输时间
AOF
AOF,英文是Append Only File ,即只允许追加不允许改写的文件。
AOF,将redis执行过得所有写指令(每秒钟),记录在日志里,再次redis重新启动时只要把这些写指令从前到后再重复执行一遍,就可实现数据恢复。
特点
实时性
完整性较好
体积大
记录/删除数据的指令,都会被记录。恢复速度慢于RDB。
开启AOF
vim /redis-4.0.9/redis.conf
appendonly yes
##此选项为aof功能的开关,默认为“no”,可以通过“yes”来开启aof功能
##只有在“yes”下,aof重写/文件同步等特性才会生效
appendfilename appendonly.aof
##指定aof文件名称
appendfsync everysec
##指定aof操作中文件同步策略,有三个合法值:always everysec no,默认为everysec
no-appendfsync-on-rewrite no
##在aof-rewrite期间,appendfsync是否暂缓文件同步,"no"表示“不暂缓”,“yes”表示“暂缓”,默认为“no”
auto-aof-rewrite-min-size 64mb
##aof文件rewrite触发的最小文件尺寸(mb,gb),只有大于此aof文件大于此尺寸是才会触发rewrite,默认“64mb”,建议“512mb”
auto-aof-rewrite-percentage 100
##相对于“上一次”rewrite,本次rewrite触发时aof文件应该增长的百分比。
##每一次rewrite之后,redis都会记录下此时“新aof”文件的大小(例如A),那么当aof文件增长到A*(1 + p)之后
##触发下一次rewrite,每一次aof记录的添加,都会检测当前aof文件的尺寸。
默认的AOF持久化策略
每秒钟fsync(把缓存中的写指令记录到磁盘中)一次,在这种情况下,redis,仍可以保持良好的处理性能,即使redis故障也只会丢失最近一秒的数据。
AOF日志修复
若在追加日志时,恰好遇到磁盘空间满,inode满或断电等情况导致日志写入不完整,redis并不会贸然加载这个有问题的AOF文件,而是报错退出。
可使用redis的提供的redis-check-aof工具,可以用来进行日志修复。
1.备份被写坏的AOF文件
2.运行redis-check-aof –fix进行修复
3.用diff -u来看下两个文件的差异,确认问题点
4.重启redis,加载修复后的AOF文件
AOF重写
AOF使用追加模式,若不做任何处理,AOF文件会越来越大,因此,redis提供了重写机制(rewrite)机制。
文件重写机制(rewrite):当AOF文件大小超过所设定的阈值时,redis会启动AOF的内容压缩,只保留可以恢复数据的最小指令集。
原理:
- 重写即将开始之际,redis会创建(fork)一个“重写子进程”,这个子进程会首先读取现有的AOF文件,并将其包含的指令进行分析压缩并写入到一个临时文件中。
- 与此同时,主工作进程会将新接收到的写指令一边累积到内存缓冲区中,一边继续写入到原有的AOF文件中,这样做是保证原有的AOF文件的可用性,避免在重写过程中出现意外。
- 当“重写子进程”完成重写工作后,它会给父进程发一个信号,父进程收到信号后就会将内存中缓存的写指令追加到新AOF文件中。
- 当追加结束后,redis就会用新AOF文件来代替旧AOF文件,之后再有新的写指令,就都会追加到新的AOF文件中了。
通过AOF恢复数据
若意外执行了FLUSHALL,导致redis内存中数据被清空。只要redis配置了AOF持久化方式,且AOF文件还没被重写,可以执行以下操作恢复。
- 暂停redis
- 编辑AOF文件将最后一行的FLUSHALL删除
- 重启redis
持久化选择RDB和AOF的选择方式
官方建议两个同时使用这样可以提供更可靠的持久化方案。
这种情况下redis重启的话,会优先采用AOF方式来进行数据恢复(AOF恢复数据完整度更高。)
AOF写入数据快,RDB写入速度慢
如果没有数据持久化需求,可以关闭RDB和AOF方式,这样的话redis将变成一个纯内存数据库,就像memcache一样。
redis主从、哨兵
^注: 摘自https://blog.csdn.net/u012152619/article/details/52854465
主从同步
redis同mysql一样支持主从同步(同时也支持一主多从以及多级从结构)
redis的主从同步是异步进行的,这种模式的优点是主从同步不会影响主逻辑,也不会降低redis的处理性能。
使用主从结构的原因
- 纯碎的冗余备份
- 提升读性能,比如很小号性能的SORT就可以有从服务器来承担。
优化
- 可以考虑关闭主服务器的数据持久化功能,只让从服务器持久化,这样可以提高主服务器的处理性能。
- 将从服务器设置为只读模式,这样可以避免从服务器数据被误修改,但从服务器仍然可以接受CONRG指令,因此不应将从服务器直接暴露到不安全的网络环境中。(如必须如此,那可以考虑给重要指令进行重命名。)
原理
如果设置了一个Slave,无论是第一次连接还是重连到Master,它都会发出一个SYNC命令;
当Master收到SYNC命令之后,会做两件事:
a) Master执行BGSAVE,即在后台保存数据到磁盘(rdb快照文件); b) Master同时将新收到的写入和修改数据集的命令存入缓冲区(非查询类);
当Master在后台把数据保存到快照文件完成之后,Master会把这个快照文件传送给Slave,而Slave则把内存清空后,加载该文件到内存中;
而Master也会把此前收集到缓冲区中的命令,通过Reids命令协议形式转发给Slave,Slave执行这些命令,实现和Master的同步;
Master/Slave此后会不断通过异步方式进行命令的同步,达到最终数据的同步一致;
需要注意的是Master和Slave之间一旦发生重连都会引发全量同步操作。但在2.8之后版本,也可能是部分同步操作。
部分复制
2.8开始,当Master和Slave之间的连接断开之后,他们之间可以采用持续复制处理方式代替采用全量同步。
Master端为复制流维护一个内存缓冲区(in-memory backlog),记录最近发送的复制流命令;同时,Master和Slave之间都维护一个复制偏移量(replication offset)和当前Master服务器ID(Masterrun id)。当网络断开,Slave尝试重连时:
a. 如果MasterID相同(即仍是断网前的Master服务器),并且从断开时到当前时刻的历史命令依然在Master的内存缓冲区中存在,则Master会将缺失的这段时间的所有命令发送给Slave执行,然后复制工作就可以继续执行了;
b. 否则,依然需要全量复制操作;
sentinel
sentinel(哨兵)
Sentinel(哨兵)是用于监控redis集群中Master状态的工具,其已经被集成在redis2.4+的版本中
setinel作用
- Master状态检测
- 如果Master异常,则会进行Master-Slave切换,将其中一个Slave作为Master,将之前的Master作为Slave
- Master-Slave切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变,即master_redis.conf中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换
sentinel工作方式
- 每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令
- 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。
- 如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。 an>
- 当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线
- 在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有Master,Slave发送 INFO 命令
- 当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次
- 若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的客观下线状态就会被移除。 若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。
主观下线和客观下线
主观下线:Subjectively Down,简称 SDOWN,指的是当前 Sentinel 实例对某个redis服务器做出的下线判断。
客观下线:Objectively Down, 简称 ODOWN,指的是多个 Sentinel 实例在对Master Server做出 SDOWN 判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下线判断,然后开启failover.
举个栗子
环境
三台服务器保持通讯畅通,并部署redis。
master slave1 slave2
配置主从
- master
# vim /etc/redis/6379.conf
master:
bind 0.0.0.0 //监控本地所有网卡IP
protected-mode no
- slave1/2
# vim /etc/redis/6379.conf
bind 0.0.0.0
slaveof master_ip master_port //修改master_ip和port
protected-mode no
测试
# /redis-4.0.9/src/redis-cli
127.0.0.1:6379> info replication
master结果
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.0.113,port=6379,state=online,offset=2212,lag=1
slave1:ip=192.168.0.112,port=6379,state=online,offset=2212,lag=0
slave结果
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.0.109
master_port:6379
master_link_status:up
配置sentienl
每台机器上修改redis主配置文件设置:bind 0.0.0.0
每台机器上修改sentinel配置文件:添加如下配置
# vim /redis-4.0.9/sentinel.conf sentinel monitor mymaster MASTERIP 6379 2 //当集群中有2个sentinel认为master死了时,才能真正认为该master已经不可用了。 sentinel down-after-milliseconds mymaster 3000 //单位毫秒 sentinel failover-timeout mymaster 10000 protected-mode no
每台机器启动服务
# ./src/redis-sentinel sentinel.conf
关闭主服务器,观察从服务器状态
# /redis-4.0.9/src/redis-cli
#info replication