NoSQL概述
NoSQL = not only SQL,即非关系型数据库。随着互联网web2.0(web1.0是由系统向用户展示内容。web2.0就是用户主动获取并产生内容。web3.0是个性化内容的获取)网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题,包括超大规模数据的存储。
传统单机 MySQL 瓶颈
- 数据量的总大小,一个机器1放不下,单表数据达到500万时MySQL性能低
- 数据的索引(B + Tree) 一个机器的内存放不下时
- 访问量(读写混合)一个实例不能承受
为什么需要NoSQL
我们可以通过第三方平台(如:Baidu,Google,Facebook等)可以很容易的访问和抓取数据。用户的个人信息,社交网络,地理位置,用户生成的数据和用户操作日志已经成倍的增加。我们如果要对这些用户数据进行挖掘,那SQL数据库已经不适合这些应用了,
NoSQL数据库的发展能很好的处理这些大数据。和传统的关系型数据库相比,NoSQL具有以下的优势:
- high performance ,高并发读写,动态页面展示与交互,比如微博点赞评论等操作,实时统计在线人数排行榜等
- huge storage,海量数据的高效存储和访问,大型网站的用户登录系统
- high scalability && high availability,高可扩展性和高可用性
主流的NoSQL产品有哪些
- redis
优势,快速查询
劣势,存储数据缺少结构化
- mongodb
- 优势,数据结构要求不严格
- 劣势,查询性能并非特别高,缺少统一查询的语法
Redis简介
- Remote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。
- 它是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
- Redis通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。
Redis 特点
- Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
- Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
- Redis支持数据的备份,即master-slave模式的数据备份。
Redis的应用场景
- 缓存
- 网站访问统计
- 任务队列
- 数据过期处理
- 应用排行榜
- 分布式集群架构中的session分离
设置Redis基本配置信息
- 修改redis配置文件
# 复制redis.conf文件到/etc目录
[root@localhost redis-4.0.6]# cp /usr/local/src/redis-4.0.6/redis.conf /etc/redis.conf
# 编辑redis.conf文件
[root@localhost ~]# vim /etc/redis.conf
# 设置redis为后台启动进程,将daemonize no 改为 daemonize yes
daemonize yes
# 修改绑定的主机地址,将#bind 127.0.0.1改成自己Linux的ip地址,去掉"#"号
bind 192.168.41.22
- 关闭redis服务,重新运行
[root@localhost bin]# ./redis-cli shutdown
# 重新启动redis加载指定的配置文件
[root@localhost bin]# ./redis-server /etc/redis.conf
- 将redis-server和redis-cli命令加入环境变量
vim /etc/proflie
# 在最后一行加入
export PATH=/usr/local/redis/bin:$PATH
- 使其立即生效
source /etc/proflie
基本命令
- redis所有命令可参考http://redisdoc.com网站
set key value 赋值
get key 取值
select index 切换库(下标从0开始)
dbsize 查看当前库key的数据
flushdb 清空当前库
flushall 清空所有库
keys * 查看所有key (keys后面参数可以用表达式代替)
? 匹配一个字符
* 匹配任意个(包括0个)字符
[] 匹配括号间的任一个字符,可以使用 "-" 符号表示一个范围,如 a[b-d] 可以匹配 "ab","ac","ad"
\x 匹配字符x,用于转义符号,如果要匹配 "?" 就需要使用 \?
exists key 判断一个键值是否存在(如果存在,返回整数类型 1 ,否则返回 0)
del key [key.....] 可以删除一个或多个键,返回值是删除的键的个数
type key 返回值可能是 string(字符串类型) hash(散列类型) list(列表类型) set(集合类型) zset(有序集合类型)
move key db 当前库就没有了,被移除了
expire key time(秒) 为给定的key设置过期时间
ttl key 查看还有多少秒过期,-1表示永不过期,-2表示已过期
Redis的五大数据类型:
- string(字符串)
- hash(哈希,类似java里的Map)
- list(列表)
- set(集合)
- zset(sorted set:有序集合)
String
String类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。string类型是Redis最基本的数据类型,一个redis中字符串value最多可以是512M。Strings 数据结构是简单的key-value类型,value其实不仅是String,也可以是数字.
应用场景:
String是最常用的一种数据类型,普通的key/ value 存储都可以归为此类.即可以完全实现目前 Memcached 的功能,并且效率更高。还可以享受Redis的定时持久化,操作日志及 Replication等功能。
EXPIRE命令业务场景
EXPIRE key second的使用场景:
1、限时的优惠活动
2、网站数据缓存
3、手机验证码
4、限制网站访客频率
key的命名建议
- key不要太长,尽量不要超过1024字节。不仅消耗内存,也会降低查找的效率
- key不要太短,太短可读性会降低
- 在一个项目中,key最好使用统一的命名模式,如user:123:password
- key区分大小写
String应用场景:
1、String通常用于保存单个字符串或JSON字符串数据
2、因为String是二进制安全的,所以可以把保密要求高的图片文件内容作为字符串来存储
3、计数器:常规Key-Value缓存应用,如微博数、粉丝数。INCR本身就具有原子性特性,所以不会有线程安全问题
List
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素导列表的头部(左边)或者尾部(右边)。它的底层实际是个链表。
应用场景:
Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现。Lists 就是链表,相信略有数据结构知识的人都应该能理解其结构。使用Lists结构,我们可以轻松地实现最新消息排行等功能。Lists的另一个应用就是消息队列,
可以利用Lists的PUSH操作,将任务存在Lists中,然后工作线程再用POP操作将任务取出进行执行。Redis还提供了操作Lists中某一段的api,你可以直接查询,删除Lists中某一段的元素。
性能总结
- 它是一个字符串链表,left、right都可以插入和添加
- 如果键不存在,创建新的链表,如果键已经存在,新增内容,如果值全部移除,对应的键也消失了
- 链表的操作无论是对头和尾效率都极高,但假如是对中间元素进行操作,效率就很惨淡了
Set
Set是string类型的无序集合。它是通过HashTable实现实现的。
应用场景:
Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。Sets 集合的概念就是一堆不重复值的组合。利用Redis提供的Sets数据结构,可以存储一些集合性的数据,比如在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能,对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。
Hash
Redis hash 是一个键值对集合。hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。类似Java里面的Map<String,Object>。
应用场景:
在Memcached中,我们经常将一些结构化的信息打包成HashMap,在客户端序列化后存储为一个字符串的值,比如用户的昵称、年龄、性别、积分等,这时候在需要修改其中某一项时,通常需要将所有值取出反序列化后,修改某一项的值,再序列化存储回去。这样不仅增大了开销,也不适用于一些可能并发操作的场合(比如两个并发的操作都需要修改积分)。而Redis的Hash结构可以使你像在数据库中Update一个属性一样只修改某一项属性值。
Zset
zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。
应用场景:
Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。还可以用Sorted Sets来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。
Redis常用配置
include(引入外部配置)
include /path/to/other.conf 这在你有标准配置模板但是每个redis服务器又需要个性设置的时候很有用
general(一般常用)
daemonize yes Redis 默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程(yes:后台运行;no:不是后台运行)
protected-mode yes 保护模式,默认开启。开启该参数后,redis只会本地进行访问,拒绝外部访问。
pidfile /var/run/redis/redis-server.pid redis的进程文件
port 6379 redis默认监听的端口号
tcp-backlog 511 TCP连接队列的长度
bind 127.0.0.1 指定redis只接收来自于该IP地址的请求,如果不进行设置,那么将处理所有请求
timeout 0 当客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
loglevel notice
指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose;
debug(很多信息,方便开发、测试)
verbose(许多有用的信息,但是没有debug级别信息多)
notice(适当的日志级别,适合生产环境)
warn(只有非常重要的信息)
logfile /var/log/redis/redis-server.log 日志记录方式,默认为标准输出,如果配置Redis为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给/dev/null。空字符串的话,日志会打印到标准输出设备。后台运行的redis标准输出是/dev/null
databases 16 设置数据库的数量,默认数据库为0,可以使用SELECT <dbid>命令在连接上指定数据库id
SNAPSHOTTING(快照)
save <seconds> <changes> <指定时间间隔> <执行指定次数更新操作>,满足条件就将内存中的数据同步到硬盘中。
save ""
save 900 1
save 300 10
save 60 10000
注释掉“save”这一行配置项就可以让保存数据库功能失效,设置sedis进行数据库镜像的频率。
900秒(15分钟)内至少1个key值改变(则进行数据库保存--持久化)
300秒(5分钟)内至少10个key值改变(则进行数据库保存--持久化)
60秒(1分钟)内至少10000个key值改变(则进行数据库保存--持久化)
stop-writes-on-bgsave-error yes 当RDB持久化出现错误后,是否依然进行继续进行工作,yes:不能进行工作,no:可以继续进行工作,可以通过info中的rdb_last_bgsave_status了解RDB持久化是否有错误
rdbcompression yes 使用压缩rdb文件,rdb文件压缩使用LZF压缩算法,yes:压缩,但是需要一些cpu的消耗。no:不压缩,需要更多的磁盘空间
rdbchecksum yes 是否校验rdb文件。从rdb格式的第五个版本开始,在rdb文件的末尾会带上CRC64的校验和。这跟有利于文件的容错性,但是在保存rdb文件的时候,会有大概10%的性能损耗,所以如果你追求高性能,可以关闭该配置。
dbfilename dump.rdb rdb文件的名称
dir /var/lib/redis 数据目录,数据库的写入会在这个目录。rdb、aof文件也会写在这个目录
REPLICATION(复制)
slaveof <masterip> <masterport> 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步
masterauth <master-password> 当master服务设置了密码保护时,slav服务连接master的密码
slave-read-only yes 作为从服务器,默认情况下是只读的(yes),可以修改成NO,用于写(不建议)。
slave-priority 100 当master不可用,Sentinel会根据slave的优先级选举一个master。最低的优先级的slave,当选master。而配置成0,永远不会被选举
SECURITY(安全)
requirepass foobared requirepass配置可以让用户使用AUTH命令来认证密码,才能使用其他命令。这让redis可以使用在不受信任的网络中。为了保持向后的兼容性,可以注释该命令,因为大部分用户也不需要认证。使用requirepass的时候需要注意,因为redis太快了,每秒可以认证15w次密码,简单的密码很容易被攻破,所以最好使用一个更复杂的密码。
LIMITS(限制)
-
maxclients 10000 设置能连上redis的最大客户端连接数量。默认是10000个客户端连接。由于redis不区分连接是客户端连接还是内部打开文件或者和slave连接等,所以maxclients最小建议设置到32。如果超过了maxclients,redis会给新的连接发送’max number of clients reached’,并关闭连接。
-
maxmemory <bytes> redis配置的最大内存容量。当内存满了,需要配合maxmemory-policy策略进行处理。注意slave的输出缓冲区是不计算在maxmemory内的。所以为了防止主机内存使用完,建议设置的maxmemory需要更小一些。
-
maxmemory-policy noeviction 内存容量超过maxmemory后的处理策略
- volatile-lru(Least Recently Used 即最近最少使用):利用LRU算法移除key,只对设置了过期时间的key。
- allkeys-lru:利用LRU算法移除所有key,与是否设置过期时间没关系。
- volatile-random:随机移除设置了过期时间的key。
- allkeys-random:随机移除任何key。与是否设置过期时间没关系。
- volatile-ttl:移除即将过期的key。
- noeviction:不移除任何key,只是返回一个写错误。
APPEND ONLY MODE(追加)
appendonly no 默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了。但是redis如果中途宕机,会导致可能有几分钟的数据丢失,根据save来策略进行持久化,Append Only File是另一种持久化方式,可以提供更好的持久化特性。Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件,每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。
appendfilename "appendonly.aof" aof文件名
appendfsync everysec aof持久化策略的配置。
no表示不执行fsync,由操作系统保证数据同步到磁盘,速度最快。
always表示每次写入都执行fsync,以保证数据同步到磁盘。
everysec表示每秒执行一次fsync,可能会导致丢失这1s数据。
auto-aof-rewrite-percentage 100 aof自动重写配置。当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写,即当aof文件增长到一定大小的时候Redis能够调用bgrewriteaof对日志文件进行重写。当前AOF文件大小是上次日志重写得到AOF文件大小的二倍(设置为100)时,自动启动新的日志重写过程。
auto-aof-rewrite-min-size 64mb 设置允许重写的最小aof文件大小,避免了达到约定百分比但尺寸仍然很小的情况还要重写
redis.conf常见配置
# Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程
daemonize no
# 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定
pidfile /var/run/redis.pid
# 指定Redis监听端口,默认端口为6379,作者在自己的一篇博文中解释了为什么选用6379作为默认端口,因为6379在手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字
port 6379
# 绑定的主机地址
bind 127.0.0.1
# 当 客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
timeout 300
# 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose
loglevel verbose
# 日志记录方式,默认为标准输出,如果配置Redis为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给/dev/null
logfile stdout
# 设置数据库的数量,默认数据库为0,可以使用SELECT <dbid>命令在连接上指定数据库id
databases 16
# 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
save <seconds> <changes>
# Redis默认配置文件中提供了三个条件:
#save 900 1 # 900秒(15分钟)内有1个更改
#save 300 10 # 300秒(5分钟)内有10个更改
#save 60 10000 # 60秒内有10000个更改
# 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大
rdbcompression yes
# 指定本地数据库文件名,默认值为dump.rdb
dbfilename dump.rdb
# 指定本地数据库存放目录
dir ./
# 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步
slaveof <masterip> <masterport>
# 当master服务设置了密码保护时,slav服务连接master的密码
masterauth <master-password>
# 设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH <password>命令提供密码,默认关闭
requirepass foobared
# 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息
maxclients 128
# 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区
maxmemory <bytes>
# 指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no
appendonly no
# 指定更新日志文件名,默认为appendonly.aof
appendfilename appendonly.aof
# 指定更新日志条件,共有3个可选值:
#no:表示等操作系统进行数据缓存同步到磁盘(快)
#always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
#everysec:表示每秒同步一次(折衷,默认值)
#appendfsync everysec
# 指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析Redis的VM机制)
vm-enabled no
# 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享
vm-swap-file /tmp/redis.swap
# 将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0
vm-max-memory 0
# Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,vm-page-size是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page大小最好设置为32或者64bytes;如果存储很大大对象,则可以使用更大的page,如果不 确定,就使用默认值
vm-page-size 32
# 设置swap文件中的page数量,由于页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,,在磁盘上每8个pages将消耗1byte的内存。
vm-pages 134217728
# 设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4
vm-max-threads 4
# 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启
glueoutputbuf yes
# 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法
#hash-max-zipmap-entries 64
#hash-max-zipmap-value 512
# 指定是否激活重置哈希,默认为开启(后面在介绍Redis的哈希算法时具体介绍)
activerehashing yes
# 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件
include /path/to/local.conf
配置信息可以通过config get
获取
config get port # 获取redis端口号
config get dir # 获取启动路径
config get requirepass # 获取密码
config set requirepass "123456" # 设置redis密码
持久化(RDB/AOF)
RDB
RDB(Redis Database) 是 Redis 默认的持久化方案。它可以在指定的时间间隔内将内存中的数据集快照写入磁盘
,
也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里,在RDB方式下,你有两种选择:
-
一种是手动执行持久化数据命令来让redis进行一次数据快照,
-
另一种则是根据你所配置的配置文件的策略,达到策略的某些条件时来自动持久化数据。
而手动执行持久化命令,你依然有两种选择:
-
save命令
save命令执行时只管保存,其他不管,全部阻塞
,save操作在Redis主线程中工作,因此会阻塞其他请求操作,应该避免使用。(默认下,持久化到dump.rdb文件,并且在redis重启后,自动读取其中文件,据悉,通常情况下一千万的字符串类型键,1GB的快照文件,同步到内存中的 时间是20-30秒) -
bgsave命令。
bgsave后台备份,在备份的同时可以处理输入的数据
,bgSave则是调用Fork,产生子进程,父进程继续处理请求。子进程将数据写入临时文件,并在写完后,替换原有的.rdb文件。Fork发生时,父子进程内存共享,所以为了不影响子进程做数据快照,在这期间修改的数据,将会被复制一份,而不进共享内存。所以说,RDB所持久化的数据,是Fork发生时的数据。在这样的条件下进行持久化数据,如果因为某些情况宕机,则会丢失一段时间的数据。如果你的实际情况对数据丢失没那么敏感,丢失的也可以从传统数据库中获取或者说丢失部分也无所谓,那么你可以选择RDB持久化方式。
### 生产环境推荐配置(系统默认的)
# 15分钟修改1次
save 900 1
# 5分钟修改10次
save 300 10
# 一分钟修改一万次
save 60 10000
### 如果想禁用
# save ""
这是配置文件默认的策略,他们之间的关系是或,每隔900秒,在这期间变化了至少一个键值,做快照。或者每三百秒,变化了十个键值做快照。或者每六十秒,变化了至少一万个键值,做快照。
RDB配置
触发RDB快照
- 在指定的时间间隔内,执行指定次数的写操作。
- 执行save(阻塞, 只管保存快照,其他的等待) 或者是bgsave (异步)命令。
- 执行flushall 命令,清空数据库所有数据,意义不大。
- 执行shutdown 命令,保证服务器正常关闭且不丢失任何数据,意义也不大。
数据恢复
将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可。
优势
- 适合大规模的数据恢复
- 对数据完整性要求不高
劣势
- 在一定时间做一次备份,如果redis意外宕机的话就会丢失最后一次快照后的所有数据
- Fork的时候,内存中的数据被克隆了一份,在fork的过程是非常耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的请求
AOF
- AOF(Append Only File) ,Redis 默认不开启。它的出现是为了弥补RDB的不足(数据的不一致性),所以它采用日志的形式来记录每个写操作,并追加到文件中。Redis 重启的会根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
- 配置文件中的appendonly修改为yes。开启AOF持久化后,你所执行的每一条指令,都会被记录到appendonly.aof文件中。但事实上,并不会立即将命令写入到硬盘文件中,而是写入到硬盘缓存,在接下来的策略中,配置多久来从硬盘缓存写入到硬盘文件。所以在一定程度一定条件下,还是会有数据丢失,不过你可以大大减少数据损失。
- 这里是配置AOF持久化的策略。redis默认使用everysec,就是说每秒持久化一次,而always则是每次操作都会立即写入aof文件中。而no则是不主动进行同步操作,是默认30s一次。当然always一定是效率最低的,个人认为everysec就够用了,数据安全性能又高
AOF配置
- 开启AOF配置
# AOF and RDB persistence can be enabled at the same time without problems.
# AOF和RDB的持久化是可以同时开启的
# If the AOF is enabled on startup Redis will load the AOF, that is the file
# 如果启动时启用了AOF, Redis将先加载AOF
# with the better durability guarantees.
# 开启aop配置
appendonly yes
# aop生成文件名称
appendfilename "appendonly.aof"
数据恢复
将备份文件 (appendonly.aof) 移动到 redis 安装目录并启动服务即可。
触发AOF快照
根据配置文件触发,可以是每次执行触发,可以是每秒触发,可以不同步。
- always:每修改同步
everysec
:每秒同步- no:不同步
# 每修改同步:同步持久化 每次发生数据变更会被立即记录到磁盘,性能较差但数据完整性比较好
appendfsync always
# 每秒同步:默认设置,异步操作,每秒记录 如果一秒内宕机,有数据丢失(推荐)
appendfsync everysec
# 不同步:从不同步
appendfsync no
AOF rewrite(重写)
-
AOF采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集.可以使用命令bgrewriteaof。
-
AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后再rename),
遍历新进程的内存中数据,每条记录有一条的Set语句。重写aof文件的操作,并没有读取旧的aof文件,
而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。 -
Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。
AOP文件修复
redis-check-aof --fix appendonly.aof
RDB & AOF比较
优势
RDB:适合大规模的数据恢复。如果业务对数据完整性和一致性要求不高,RDB是很好的选择。
AOF:数据的完整性和一致性更高。
劣势
RDB:数据的完整性和一致性不高,因为RDB可能在最后一次备份时宕机了。 备份时占用内存,因为Redis 在备份时会独立创建一个子进程,将数据写入到一个临时文件(此时内存中的数据是原来的两倍哦),最后再将临时文件替换之前的备份文件。所以Redis 的持久化和数据的恢复要选择在夜深人静的时候执行是比较合理的。
AOF:因为AOF记录的内容多,文件会越来越大,数据恢复也会越来越慢。
总结
- Redis 默认开启RDB持久化方式,在指定的时间间隔内,执行指定次数的写操作,则将内存中的数据写入到磁盘中。
- RDB 持久化适合大规模的数据恢复但它的数据一致性和完整性较差。
- Redis 需要手动开启AOF持久化方式,默认是每秒将写操作日志追加到AOF文件中。
- AOF 的数据完整性比RDB高,但记录内容多了,会影响数据恢复的效率。
- Redis 针对 AOF文件大的问题,提供重写的瘦身机制。
- 若只打算用Redis 做缓存,可以关闭持久化。
- 若打算使用Redis 的持久化。建议RDB和AOF都开启。其实RDB更适合做数据的备份,留一后手。AOF出问题了,还有RDB
事物
redis的事务中,一次执行多条命令,本质是一组命令的集合,一个事务中所有的命令将被序列化,即按顺序执行而不会被其他命令插入在redis中,事务的作用就是在一个队列中一次性、顺序性、排他性的执行一系列的命令。事务可以一次执行多个命令, 并且带有以下两个重要的保证:
-
事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
-
事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。
使用事物
用multi命令开启事物,用exec执行事物。
执行结果:
① 正常执行完成;
② 有命令入队不成功,事物执行失败,全部命令都不执行;
③ 命令入队成功,事物照常执行,有命令执行失败,其余命令正常执行;
放弃事物
在使用multi开起事物之后,可以使用discard放弃当前事物。
事物-监控
redis可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行。监控一直持续到EXEC命令(事务中的命令是在EXEC之后才执行的)。
监控
watch key [key ...]
放弃监控
unwatch 取消 WATCH 命令对所有 key 的监视。
消息发布订阅
消息发布订阅是什么
-
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
-
Redis 客户端可以订阅任意数量的频道。
-
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:
发布订阅命令
序号 | 命令及描述 |
---|---|
1 | PSUBSCRIBE pattern [pattern …] 订阅一个或多个符合给定模式的频道。 |
2 | PUBSUB subcommand [argument [argument …]] 查看订阅与发布系统状态。 |
3 | PUBLISH channel message将信息发送到指定的频道。 |
4 | PUNSUBSCRIBE [pattern [pattern …]] 退订所有给定模式的频道。 |
5 | SUBSCRIBE channel [channel …]订阅给定的一个或多个频道的信息。 |
6 | UNSUBSCRIBE [channel [channel …]]指退订给定的频道。 |
示例
-
可以一次性订阅多个
SUBSCRIBE c1 c2 c3
-
消息发布
PUBLISH c1 helloredis
-
订阅多个可以使用通配符*
PSUBSCRIBE new*
-
接收消息
PUBLISH new1 redis2018 PUBLISH new2 redis2018
主从复制
在Redis中,用户可以通过执行SLAVEOF命令或者设置slaveof选项,让一个服务器去复制(replicate)另一个服务器,我们称呼被复制的服务器为主服务器(master),而对主服务器进行复制的服务器则被称为从服务器(slave)。通常用作读写分离,以及数据恢复。
配置主从
认主:
在从库里使用slaveof命令,从库认主后,从库只能做读操作;
当主机挂求后,从机原地待命;
当从机挂求重启后,从机变主机;
当使用redis.conf认主,不使用命令配置认主。
slaveof host port 认主
info [section] 查看redis信息(带replication参数可直接看主从信息)
SLAVEOF no one 将从库转成主库,并保已有数据
哨兵模式
Redis的主从架构,如果master发现故障了,还得手动将slave切换成master继续服务,手动的方式容易造成失误,导致数据丢失,那Redis有没有一种机制可以在master和slave进行监控,并在master发送故障的时候,能自动将slave切换成master呢?有的,那就是哨兵。
哨兵的作用:
- 监控redis进行状态,包括master和slave
- 当master down机,能自动将slave切换成master
配置哨兵:
新建配置文件,命名为sentinel.conf,输入下面内容
sentinel monitor mymaster 192.168.137.101 6379 1
#sentinel auth-pass myMaster master123 #配置密码
mymaster :master服务的名称,随便定义
启动哨兵:
redis-sentinel sentinel.conf