Redis(配置)
阅读数:211 评论数:0
跳转到新版页面分类
架构学
正文
Redis是一个开源的,使用C语言编写的、支持网络交互的、可基于内存也可持久化的key-value数据库。
一、Redis的持久化
Redis提供了两种持久化的方式,分别是RDB(Redis DataBase)和AOF(Append Only File)。
RDB,简单说就是在不同的时间点,将Redis存储的数据生成快照并存储到磁盘等介质上。
AOF,则是换了一个角度来实现持久化,那就是将Redis执行过的所有写指令记录下来,在下次Redis重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复。
如果RDB和AOF同时使用,Redis重启的话,则会优先采用AOF方式来进行恢复,这是因为AOF方式的数据恢复完整度更高。
Redis在进行数据持久化过程中,会先将数据写到一个临时文件中,待持久化过程都结束了,才会用这个临时文件替换上次久化好的文件。正是这种特性,让我们可以随时进行备份,因为快照文件总是完整可用的。
对于RDB方式,Redis会单独创建一个子进程来进行持久化,而主进程是不会进行任何IO操作的,这样就确保了Redis极高的性能。
如果对于数据恢复的完整性不是非常敏感,RDB方式要比AOF更加高效,如果对数据的完整性非常敏感,当Redis故障时,仍然会有近5分钟的数据丢失。
默认的AOF持久化策略是每秒钟fsync一次(fsync是指把缓存中的写指令记录到磁盘中),因为在这种情况下,Redis仍然可以保持很好的处理性能、即使Redis故障,也只会丢失最近1秒的数据。
如果在追加日志时,恰好遇到磁盘空间满、inode满或断电等情况导制日志写入不完整,也没有关系,Redis提供了redis-check-aof工具,可以用来进行日志修复。
Redis提供了AOF文件重写机制,即当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。
在进行AOF重写时,仍然采用先写临时文件,全部完成后再替换的流程。如果直接执行bgrwriteaof命令,那么Redis会生成一个全新的AOF文件。
在重写即将开始之际,Redis会创建一个“重写子进程”,这个子进程会首先读取现有AOF文件,并将其包含的指令进行分析压缩并写到一个临时文件中。与此同时,主工作进程会将新接收到写指令一边累积到内存缓存区中,一边继续写入原有的AOF文件中,这样做是保证原有的AOF文件的可用性,避免在重写过程中出现意外。当“重写子进程“完成重写工作后,它会给父进程发一个信号,父进程收到信号后就会将内存中缓存的写指令追加到新AOF文件中。当追加结束后,Redis就会用新的AOF文件来代替旧的AOF文件,之后再有新的写指令,就都会追加新的AOF文件中了。
二、主从
Redis支持主从同步,而且也支持一主多从以及多级结构。在主从架构中,从服务器通常被设置为只读模式,这样可以避免从服务器的数据被误修改。但是从服务器仍然可以接受CONFIG等指令,如果必须将从服务器直接暴露到不安全的网络环境中,可以考虑给重要指令进行重命名,来避免被外人执行。
在主从架构中,可以考虑关闭服务器的数据持久化功能,只让从服务器进行持久化,这样可以提高主服务器的处理性能。
Redis的主从同步是异步进行的,这意味着主从同步不会影响主逻辑,也不会降低Redis的处理性能。从服务顺向主服务器发出SYNC指令,当主服务器接受到此命令后,就会调用BGSAVE指令来创建一个子进程专门进行数据持久化工作,也就是将主服务器的数据写入RDB文件中。在BGSAVE指令执行完成后,主服务器会将持久化好的RDB文件发送给从服务器,从服务器接到此文件后会将其存储到磁盘上,然后再读取到内存中。这个动作完成后,主服务器会将这段时间缓存的写指令再以Redis协议的格式发送给从服务器。
三、事务
MULTI | 用来组装一个事务 |
EXEC | 用来执行一个事务 |
DISCARD | 用来取消一个事务 |
WATCH | 用来监视一些key,一旦这些key在事务执行之前被改变,则取消事务的执行。支持同时监视多个key。 |
四、配置
daemonize | 默认情况下,Redis并不是以daemon形式来运行的。当以daemon形式运行时,Redis会生成一个pid文件,默认会生成在/var/run/redis.pid,也可以通过pidfile来指定文件生成的位置。 |
bind | 默认情况下,Redis会响应本机所有可用网卡的连接请求,可以通过bind配置项来指定要绑定的IP。 |
port | 默认服务端口是6379,可以通过port配置项来修改,如果端口设置为0的话,Redis便不会监听端口了。 |
unixsocket | 还支持unix socket方式来接收请求,可以通过unixsocket配置项来指定unix socket文件路径,并通过unixsocketperm来指定文件的权限。 |
timeout |
当一个redis-client一直没有请求发向server端,那以server端有权主动关闭这个连接,可以通过timeout来设置空闲超时时限,0表示永不关闭。 |
tcp-keepalive |
TCP连接策略,可以通过tcp-keepalive配置项来进行设置,单位为秒,如果设置为0,则不会进行保活检测。 |
loglevel |
通过loglevel配置项设置日志等级,共分四级,即debug verbose notice warning |
logfile |
通过logfile配置项来设置文件的生成位置。如果设置为空,则Redis会将日志输出到标准输出。在daemon情况下,日志会被写到/dev/null中。 |
syslog-enabled |
如果希望日志打印到syslog中,通过syslog-enabled来控制。另外,syslog-ident还可以让你指定syslog里的日志标志。 |
databases |
通过databases可以设置数据库的总数量。数据库编号从0开始。 |
stop-writes-on-bgsave-error |
如果用户开启了RDB,那么Redis持久化失败时,Redis会停止接受所有的写请求,也可以使用stop-writes-on-bgsave-error来关闭这个功能。 |
rdbcompression |
对于存储到磁盘的快照,可以设置是否进行压缩存储,如果是的话,Redis会采用LZF算法进行压缩。可以使用rdbcompression配置项来关闭这个功能。 |
rdbchecksum |
在存储快照后,可以使用CRC64算法来进行数据检验,但是这样会增加性能消耗,可以使用rdbchecksum 配置项来关闭此功能。 |
dbfilename | 可以通过dbfilename来设置快照文件的名称 |
dir |
可以通过dir来设置快照文件存放在路径。 |
requirepass |
如果主Redis设置了验证密码的话(使用requirepass来设置),则在从Redis的配置中要使用masterauth来设置检验密码。 |
slave-read-only |
通过slave-read-only来设置从Redis是否只读。 |
rename-command |
只读的从Redis并不适合直接暴露给不可信的客户端,可以使用rename-command指令来将一些可能有破坏办的命令重命名。 |
repl-ping-slave-period |
从Redis会周期性的向主Redis发PING包,可以通过repl-ping-slave-period指令控制其周期。 |
repl-disable-tcp-nodelay |
可以通过repl-disable-tcp-nodelay来设置 主从同步时是否禁用TCP_NODELAY,如果开启了TCP_NODEPLAY,那么主Redis会使用更少的TCP包和更少的带宽来向从Redis传输数据。但是这可能会增加一些同步的延迟,大概会达到40毫秒。 |
repl-backlog-size |
通过repl-backlog-size设置同步队列长度,队列长度(backlog)是主Redis的一个缓冲区,在与从Redis断开连接期间,主Redis会用这个缓冲区来缓存应该发给从Redis的数据。这样的话,当从Redis重新连接上之后,就不必重新全量同步数据。 |
repl-backlog-ttl |
如果主Redis等待了一段时间之后,还是无法连接上从Redis,那么缓冲队列中的数据将被清理掉,这个时间可以通过repl-backlog-ttl设置,如果设置为0,则表示永不清理。 |
slave-priority |
在众多的从Redis中可以设置优先级,在主Redis不正常的情况下,优先级高的从Redis将会升级为主Redis,slave-priority,如果设置为0,这个从Redis永远也不会被选中。 |
min-slaves-to-write |
假如主Redis发现有超过M个从Redis的连接延时超过N秒,那么主Redis就停止接受外来的写请求。如果min-slaves-to-write 3, min-slaves-max-lag 10,那么有3个从Redis的连接延迟超过10秒,那么主Redis就不再接爱外部的写请求。上述两个配置中有一个被置为0,则这特性将被关闭。 |
equirepass | 可以设置密码验证 |
rename-command |
如果把命令改为空安符串,就是禁用掉CONFIG命令。 |
maxclients | 设置Redis同时可以与多少个客户端进行连接,当你无法设置进程文件句柄限制时,Redis会设置为当前的文件句柄限制值减去32,因为Redis会为自身处理逻辑留一些句柄。 |
maxmemoery <bytes> | 设置Redis可以使用的内存理,一旦到达内存使用上限,Redis会尝试移除内部数据,移除规则可以通过maxmemory-policy来指定。 |
maxmemory-policy | 可以是volatile-lru(LRU算法移除过期集合中的key)、allkey-lru(使用LRU算法移除key)、volatile-random(在过期集合中移除随机的key)、allkeys-random(移除随机的key)、volatile-ttl(移除那此TTL值最小的key)、noeviction(不进行移除,只是返回错误信息) |
appendfilename | 设置aof文件的名称 。 |
appendfsync | aof缓存的模式(no=让操作系统自行决定,always=每次写请求,everysec=每秒) |
no-appendsync-on-rewrite | 如果后台持久化需要一个很大的IO操作,那么Redis可能会在fsync调用时卡住,使用这引配置项 |
auto-aof-rewrite-percentage和auto-aof-rewrite-min-size | 用于Redis自动启动重写。 |
lua-time-limit(ms) | ,设置lua脚本的最大运行时间,如果设置为0或负数,则不会有时间限制。 |
slowlog-log-slower-than slow-max-len |
慢日志是用于Redis记录那些超过指定查询时间的日志,执行的时间不包括和客户羰的IO操作和响应时间等,而只是Redis执行命令的时间。针对慢日志,可以设置两个参数,一个是执行时长,另一个是长度。 |
include /path/to/other.conf
五、Redis数据类型
这是简单的key-value类型,value其实不仅是String,也可以是数字。
应用场景:可以完全实现目前Memcached的功能,并且效率更高。
Redis Hash对应的Value内部实现就是一个HashMap,实际这里会有两种不同实现,这个Hash的成员比少时Redis为节省内存会采用类似一维数组的方式秋紧凑存储,而不会采用真正的HashMap结构,对应的redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。
Redis的list的实现为一个双向链表,即可以支持查找和遍历,更方便操作,不过带了部分额外的内存开销。
实现方式:set的内部实现是一个value永远为null的HashMap,实际就是通过计算hash方式来快速排重。
内部使用HashMap和跳表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳表里存放的是所有成员,使用跳表的结构可以获得比较高的查找效率,并且在实现上比较简单。
六、API的原子性
Redis的操作之所以是原子性的,是因为Redis是单线程的。对Redis来说,执行get、set等API,都是一个一个的任务,这些任务都会由Redis的线程去负责执行,任务要么执行失败,要么成功。Redis本身提供的所有API都是原子操作,Redis中的事务其实是要保证批量操作的原子性。
七、集群搭建(Redis5)
1、安装gcc
2、安装redis5(make & make install)
3、修改redis配置文件
protected-mode no # 关闭保护模式 打开(yes)时下边bind配置才生效
daemonize yes # 守护进程模式开启(后台启动)
#bind 127.0.0.1 #默认只监听本机访问也可以将需要访问的IP空格分隔添加在后面,需要注释掉
cluster-enabled yes #启用集群
cluster-config-file nodes-6379.conf #集群节点配置文件
4、新建集群节点文件夹
此前准备了两台机器:10.1.101.88、10.1.101.89 本文集群试用三主三从六个节点,所以分别在两台机器上创建三个文件夹为:
/u01/redis/cluster/6379
/u01/redis/cluster/6380
/u01/redis/cluster/6381
5、拷贝配置文件
分别将redis.conf拷贝到以上两个文件夹并修改端口号。
6、启动redis
redis-server /u01/redis/cluster/6379/redis_6379.conf
redis-server /u01/redis/cluster/6380/redis_6380.conf
redis-server /u01/redis/cluster/6381/redis_6381.conf
7、启动集群
redis-cli --cluster create 10.1.101.88:6379 10.1.101.89:6379 10.1.101.88:6380 10.1.101.89:6380 10.1.101.88:6381 10.1.101.89:6381 --cluster-replicas 1
8、常见问题
(1)No route to host
是防火墙的问题。
(2)waiting for the cluster to join
redis集群不仅需要开通redis客户端的端口,还需要开通集群总线端口,集群总线端口为redis客户端连接的端口+10000
(3)node is not empty
将此节点下的aof rdb nodes.conf删除之后再执行集群创建。
9、检查集群
redis-cli --cluster check 10.1.101.88:6379