数据库缓存

数据库缓存

许多web停用都将数据保存到RDBMS(关系型数据库)中,应用服务器中读取数据并在浏览器中显示。但随着数据量增大、访问的集中,就会出现RDBMS的负担加重,数据库响应恶化,网站显示延迟等重大影响。

Memcahe/redis是高性能的分布式内存缓存服务器,通过缓存数据库查询结果,减少数据库访问次数,以提高动态web等应用速度,提高可扩展性。

简而言之:缓存数据库查询结果,加快访问速度,缓解数据库压力。

Nosql

非关系型数据库(not only sql)

  • 为弥补关系型数据库的不足
  • 以键值方式存储数据
  • 缓存数据库
  • 产品有redis、memcached、mongoDB

Memcache

特点

  • 内置内存存储方式(重启操作系统会导致全部数据消失)
  • 简单的key/value存储
  • 不互相通信的分布式

缓存原理

  1. 检查用户请求的数据时缓存中是否存在,若存在直接返回,无需查询数据库。
  2. 若请求数据在缓存中查询不到,去查询数据库,返回数据,同时把数据存储到缓存中一份。
  3. 保持缓存的“新鲜性”,每当数据发生变化的时候,要同步更新缓存的信息,确保用户不会在缓存取到旧的数据。

Redis

redis是一个开源的,使用C语言编写的,支持网络交互的,可基于内存也可持久化的key-Value数据库。

官网:redis.io

特点

  1. 丰富的数据结构
  2. 支持持久化
  3. 支持事物(事物:一个完整的动作,要么全部执行,要么什么都没做。)
  4. 支持主从

安装

从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)

注意:

  1. key不可太长,尽量不要超过1024字节,这样不仅会小孩内存,而且会降低查找效率。
  2. key也不要太短,太短的话,key的可读性会降低。
  3. 在项目中,建议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    
##如下为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指令,因此不应将从服务器直接暴露到不安全的网络环境中。(如必须如此,那可以考虑给重要指令进行重命名。)
原理

redis主从同步

  1. 如果设置了一个Slave,无论是第一次连接还是重连到Master,它都会发出一个SYNC命令;

  2. 当Master收到SYNC命令之后,会做两件事:

    a) Master执行BGSAVE,即在后台保存数据到磁盘(rdb快照文件);
    
    b) Master同时将新收到的写入和修改数据集的命令存入缓冲区(非查询类);
    
  3. 当Master在后台把数据保存到快照文件完成之后,Master会把这个快照文件传送给Slave,而Slave则把内存清空后,加载该文件到内存中;

  4. 而Master也会把此前收集到缓冲区中的命令,通过Reids命令协议形式转发给Slave,Slave执行这些命令,实现和Master的同步;

  5. Master/Slave此后会不断通过异步方式进行命令的同步,达到最终数据的同步一致;

  6. 需要注意的是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作用
  1. Master状态检测
  2. 如果Master异常,则会进行Master-Slave切换,将其中一个Slave作为Master,将之前的Master作为Slave
  3. Master-Slave切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变,即master_redis.conf中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换
sentinel工作方式
  1. 每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令
  2. 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。
  3. 如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。 an>
  4. 当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线
  5. 在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有Master,Slave发送 INFO 命令
  6. 当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次
  7. 若没有足够数量的 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
  1. 每台机器上修改redis主配置文件设置:bind 0.0.0.0

  2. 每台机器上修改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
  3. 每台机器启动服务

       # ./src/redis-sentinel sentinel.conf
  4. 关闭主服务器,观察从服务器状态

   # /redis-4.0.9/src/redis-cli 
   #info replication

你可能感兴趣的:(运维)