Redis配置
Redis可以使用内置的默认配置文件,但只能用来测试和开发。因此,最好自己配置Redis配置文件,通常叫做redis.conf。也可以直接使用命令行传送Redis配置参数,但一般用来测试。这时,会在内部生成的一个临时内存配置文件,文件参数会被翻译成redis.conf的格式。
运行时更改配置:
使用命令 CONFIG SET和CONFIG GET,如果更改的配置没有对redis.conf产生影响,重启的Redis还是会使用原来的配置文件。需要使用CONFIG SET确保修改了redis.conf。
配置Redis作为缓存:
每个key需要一个过期集合。
maxmemory 2mb maxmemory-policy allkeys-lru
当超过2M的限制后,使用LRU算法除去key。
如果需要存储数据,可以在创建一个实例作为存储,根据你的持久性的需求配置和只保存不与缓存数据相关的key。
Redis设置注意事项
1. 使用Linux
2. 将Linux内核的overcommit memory设置1。添加vm.overcommit_memory=1到/etc/sysctl.conf或者使用命令sysctlvm.overcommit_memory=1
3. 设置swap内存。如果Linux没有swap,Redis实例消耗了太多内存,Redis会由于内存不足崩溃或者Linux内核的OOM killer会杀死Redis进程
4. 如果Redis处理写负载较重的应用时,在磁盘上保存RDB文件或者重写AOF日志会使用2倍于通常使用的内存。额外的内存用来成比例的存储一定数量被写操作改变的内存页,因此,同时也会影响一定比例数量的key
5. 即使关闭持久化,在使用复制时,Redis会执行RDB保存
6. Redis持久化不推荐使用EC2 EBS卷,EBS性能较低。使用临时存储保存持久化,如果可能将持久化文件移到EBS
7. 使用虚拟机部署Redis,虚拟化管理程序调用fork()很慢。根据数据集大小,阻塞Redis几毫秒到几秒。
不停机升级和重启Redis实例:
目前为止,绝大数情况在不停止Redis修改配置的方法使用 CONFIG SET命令常用方式:
1. 为你当前的Redis实例设置一个从Redis实例。需要不同的服务器或者一台足够内存的服务器2. 如果在一台服务器,确保在不同的端口启动
3. 等待复制初始同步完成4. 使用INFO确保主从实例含有同样数量的key,使用redis-cli检测从服务器是否如你所愿的工作和回复命令
5. 配置客户端使用从实例6. 当你确定主实例不在接受任何查询(使用MONITOR命令检查),用SLAVEOF NO ONE命令执行升级从实例为主实例,然后关闭主实例。
主从复制
Redis主从复制的特性:
1. 一个主服务器可以有多个从服务器
2. 从服务器可以接受来自其他从服务器的连接。
3. Redis复制在主服务器端是无阻塞的。在从服务器执行第一次同步的时候,主服务器可以继续执行查询操作。
4. 在从服务器端也是无阻塞的。当从服务器第一次执行同步的时候,如果你在redis.conf配置了,可以使用旧的数据作为查询结果。也可以配置从服务器在与主服务器的连接down掉的时候,向客户端发送错误。但是也会有阻塞的时候,当旧数据必须被删除,新的数据加载进来的时候,从服务器会阻塞进入的连接。
5. 可以让从服务器执行保存数据的操作。
复制工作方式
建立从服务器后,使用连接发送SYNC命令,第一次连接或者重连接都可以。主服务器在后台执行保存,收集会更改数据的命令,当后台保存完毕,主服务器将保存在磁盘中的数据文件传输到从服务器,从服务器将它们载入内存。主服务器把收集到的命令发送给从服务器。
当连接断掉后,从服务器可以自动重新连接到主服务器。但是,当主服务器和从服务器重连接down掉后,就会会开始一个新的同步。
配置(slave配置文件):
slaveof master ip port
从服务器默认设置为只读模式,这样就不会被暴露在因特网中,或者网络中不信任的客户端。因为在重新同步或者从服务器重启时,写操作会被丢弃,但经常有部分不重要的临时数据保存在从服务器上,客户端可能会读取,造成数据不协调。
验证主服务器:
config set masterauth <password>或者在配置文件中使用masterauth <password>
Redis持久性
Redis持久性一般为以下几种:
1. RDB持久性对你的数据在指定的时间执行实时快照
2. AOF持久性由服务器记录每一次写操作,在重启服务器的时候,重构源数据。以Redis协议的格式记录命令。当日志变得太大的时候,Redis会在后台重写日志文件。
3. 可以同时使用RDB和AOF,但恢复数据的时候使用AOF文件,因为记录了完整的操作。
RDB优点:
1. 压缩的单一文件,可以实时的反映Redis数据。RDB文件可以作为备份。
2. 可以很方便的迁移。
3. RDB最大的提升Redis性能,因为Redis parent进程只需要fork一个子进程,然后子进程处理剩下操作。
4. RDB恢复大数据比AOF快。
RDB缺点:
1. 当Redis意外停止工作时,数据丢失会较大。
2. RDB需要经常调用fork(),让子进程持续进行磁盘操作。fork()可能会耗费大量时间,如果数据比较大,还可能会导致Redis停止服务几毫秒,甚至一秒。如果数据非常大和CPU性能不是很好,会花费大量时间。
AOF优点:
1. 有不同的fsync选择:不执行fsync,每秒一次fsync,每次查询时fsync。默认使用每秒一次fsync,只会损失一秒的写操作。fsync被后台线程执行,主线程尽力执行写操作直到没有fsync操作。
2. AOF日志只能被添加,不能搜索,如果断电也不会被污染。
3. 当文件太大的时候,会在后台自动重写AOF。即使Redis继续向旧文件添加数据,重写也是完全安全的,也会以最少的操作对当前的数据集创建一个新的AOF文件,当新文件创建好了,Redis切换两个文件,以后向新的文件添加log。
4. AOF文件简单容易理解。
AOF缺点:
1. 同样的数据集AOF文件比RDB文件大
2. 使用精确的fsync策略AOF文件执行比RDB慢。RDB可以保证在很大的延迟甚至是巨大的写负载都能很效的执行。
3. 目前有一个罕见的bug,重载数据时不是十分准确。RDB没有这个bug。原因是AOF文件增量的更新现有状态,RDB快照每次都从头开始。
RDB 支持连续快照
Redis将数据快照保存在磁盘上,是一个叫dump.rdb的二进制文件。可以配置Redis每隔N秒至少数据集有M个改变时保存数据。
save 60 1000
Redis RDB转储数据到磁盘上执行的操作:
1. Redis调用fork,然后有一个子进程和一个父进程。
2. 子进程将数据写到一个临时RDB文件
3. 当子进程写完一个新的RDB文件时,替换原来的文件。
Append-only文件
在配置文件中打开AOF
appendonly yes
每次Redis收到的改变数据集的命令,都会添加到AOF文件。
当你重启Redis文件时,AOF会被执行恢复Redis原来的状态
日志重写
自动在后台重写AOF日志并不中断对客户端的服务。
AOF持久策略
同步数据到磁盘上的选项:
1. 每次一个命令加入到AOF时执行fsync。很慢,但安全
2. 每秒一次fsync。足够快,但会损失一秒的数据
3. 从不fsync,将数据保存在操作系统中。最快,最不安全。
AOF文件崩溃处理办法
1. 对你的AOF文件做备份
2. 使用redis-check-aof工具修复原始文件:redis-check-aof --fix
3. 选择性的使用diff -u检查两个文件的不同
4. 重启server并使用修复的文件
AOF工作方式:
1. Redis调用fork
2. 子进程在一个临时文件写新的AOF
3. 父进程在内存缓冲区中聚集所有新的改变。(同时也会将新的改变写到旧的append-only文件)
4. 当子进程写完文件后,父进程得到一个信号,添加内存缓冲区中的数据到子进程产生的文件。
5. Redis自动重命名旧的文件到新的,开始添加新数据到新的文件。
从dump.rdb快照切换到AOF
1. 对你最近的dump.rdb文件做备份
2. 将备份迁移到安全的地方
3. 执行:redis-cli config set appendonly yes redis-cli config set save ""
4. 确认你的数据库包含同样数量的key
5. 确保写操作被正确的添加到append only文件
第一个CONFIG命令打开Append Only File。Redis将会阻塞初始dump,然后为写打开文件,然后添加接下来所有的写查询。
第二个CONFIG命令关闭持久快照。
注意:需要编辑redis.conf文件打开AOF,否则重启server后改变的配置操作会丢失,然后以原来的配置启动
AOF和RDB持久化之间的联系
当一个RDB快照操作在执行时,不会触发AOF重写,当AOF重写正在执行时,允许执行BGSAVE命令。可以防止两个后台进程同时做大量的磁盘I/O。
在处理快照时,用户明确的请求一个日志重写操作通过使用 BGREWRITEAOF ,服务器返回OK状态码告诉用户操作已经被安排,当快照完成后重写被立刻执行。
备份Redis数据
在数据库运行的时候你也可以copy RDB文件,因为RDB文件只要产生了就不会改变,产生的时候使用临时名字,当新的快照完成后,自动调用rename(2)重命名为最终的名字。
1. 在你的服务器创建一个定时任务,在一个目录中创建每小时的快照RDB文件,在另一个不同的目录创建每日快照
2. 每次运行计划任务脚本时,确保调用find命令删除太久的快照,比如保有最近48小时的每小时快照,和一两个月的每日快照。确保正确命名数据快照和时间信息。
3. 至少每天一次将RDB快照迁移出你的数据中心或者迁移出正在运行Redis实例的机器
灾难恢复
将你的容灾系统挂载在Amazon S3或者其他相似的服务上。将你的日常或者小时快照以加密的形式迁移到S3。
将你的快照使用scp迁移到远端服务器。
Redis安全
Redis安全模型
Redis设计在信任的环境被信任的客户端访问。不能直接暴露在网络中,或者应用环境中被不安全的客户端用TCP端口或者UNIX套接字访问。
Redis常被用来作为数据库,缓存,或者消息队列系统。客户端应用在web端查询Redis生成页面,或者请求执行操作或者web应用程序用户触发执行。
Web应用是不信任客户端和Redis的中间层
一般安全的做法,访问Redis应该经由一层实现ACLs,验证用户输入,然后再决定哪些操作送往Redis实例。但是,Redis相比于其性能和简单性,安全性还不够。
网络安全
Redis端口应该只允许信任的客户端访问。运行Redis的服务器只能被使用Redis实现的计算机应用程序直接访问
端口使用防火墙可以阻止外界的访问,但客户端仍可以使用loopback接口访问。
身份验证功能
Redis不实现访问控制,但提供一层身份验证,可以在redis.conf文件编辑打开。
使用了身份验证功能,Redis拒绝不能被验证的客户端的任何查询。客户端发送AUTH命令和密码去验证身份
密码设置在redis.conf,密码设置足够长防止蛮力攻击。
身份验证功能在防火墙或者其它保护措施失效后,能起一定保护作用
AUTH命令和其他Redis命令一样,没有被加密,不能阻止有足够能力进入网络进行窃取的攻击者
Redis本身不支持加密,可以加一个SSL代理
禁止指定的命令
禁止命令或者重命名为不能猜测的名字,限制客户端执行一些指定的命令
rename-command CONFIG ""(禁止命令)
从外部精心挑选的输入引发的攻击
一类攻击可以不通过访问进入实例引发。可以插入数据触发Redis内部的实现数据结构的算法时间复杂度变糟糕,比如通过表单提交,一些字符串应该被散列相同的桶里变结果到了hash表,O(1)变为O(N)。为了预防,Redis使用了每次执行伪随机种子的hash函数。
Redis实现SORT命令使用了qsort算法,目前,算法不是随机的,可以通过仔细选择正确的输入触发最糟糕的二次项行为
字符串转义和NoSQL注入
Redis协议没有转义字符串的概念,不会发生注入。协议使用前缀长度的字符串,完全二进制安全。
代码安全
客户端可以完全使用命令集,但访问实例不能控制当前运行的Redis系统。
在内部,Redis使用了众所周知的编程实践编写安全的代码,阻止缓冲区溢出,格式bug,和其他的一些内存泄露。客户端使用CONFIG命令改变服务器的配置,比如改变工作目录和转储文件。还允许客户端把RDB Redis文件写在随机路径中。这会容易产生安全问题允许运行不安全的代码。
Redis不需要root权限运行。
Redis基准测试
Redis含有redis-benchmark功能模仿N个客户端同时发送总共M个查询执行SETs/GETs操作。
redis-benchmark [-h <host>] [-p <port>] [-c <clients>] [-n <requests]> [-k <boolean>]
-h <hostname> 主机名 (默认 127.0.0.1)
-p <port> 主机端口 (默认 6379)
-s <socket> 主机套接字 (覆盖主机和端口)
-c <clients> 并发连接的数量 (默认 50)
-n <requests> 请求总数 (默认 10000)
-d <size> SET/GET数据的字节大小(默认 2)
-k <boolean> 1=keep alive 0=reconnect (默认 1)
-r <keyspacelen> SET/GET/INCR使用随机产生的key, SADD使用随机值使用这个选项 get/set keys时会用mykey_rand:000000012456代替常量key,
<keyspacelen>参数决定了随机数产生的最大值,比如,设置参数为10,那么产生的随机数范围是rand:000000000000 -
rand:000000000009
-P <numreq> Pipeline请求的数量. 默认 1 (不使用pipeline).
-q 展示query/sec值
--csv 以CSV格式输出
-l 本地循环. 一直运行测试
-t <tests> 在运行逗号分割列表的测试. 测试的名字与产生输出的名字一样。
-I 空闲模式. 打开 N 个空闲连接,然后等待.
如果将Redis和其他的比较,重要的是比较功能和技术上的差异,下面是需要考虑的要点:
- Redis是一个服务器,会执行所有网络上的命令和IPC循环。
- Redis命令承认所有通常使用的命令。
- 同步的迭代Redis命令并不是在基准测试Redis,应该测试网络或者IPC延迟。
- Redis在内存中存储数据并带有一些持久化保存数据的选项。
- Redis是单线程服务器,不能从多核中获益。
影响Redis性能的因素
1. 网络带宽和延迟。在执行基准测试前使用ping快速检测客户端和服务器端的延迟是一个良好的做法。对于带宽,比较好的做法是估计Gbits/s 的吞吐量和网络的理论带宽值比较。在很多实际的情况,Redis的吞吐量在网络之前会受限于CPU。
2. CPU也会是一个重要因素。由于单线程的,Redis受益于快速的含有巨大缓存的CPU。
3. 内存的速度和容量对于小的对象影响不大。但对于大于10KB的对象,可能对需要注意。通常购买昂贵的快速内存模块并不是真正的很有效。
4. Redis在虚拟机上运行慢。虚拟化对很多普通操作来说代价太高了,Redis并没有增加多少开销在所需的系统调用和网络中断上。
5. 客户端和服务器在一台机器运行,对于基准测试TCP/IP回送和UNIX域套接字都可以使用。取决于平台,但UNIX域套接字比TCP/IP回送增加50%的吞吐量。
6. 当大量使用 pipelining时,UNIX域套接字获得的性能好处会减少。
7. 当以太网访问Redis时,在数据大小小于以太网数据包的大小(大约1500字节)时,聚集命令使用 pipelining会非常有效。
8. 在多CPU套接字服务器,Redis的表现变得依赖于NUMA配置和处理位置。
9. 在高端配置,客户端连接的数量也是一个重要的因素。基于epool/kqueue模型,Redis的事件循环是相当可伸缩的。
10. 在高端的配置,通过调优NIC(s)配置和相关中断可能取得高吞吐量。
11. 根据平台,Redis编译可以使用不同的内存分配器,这可能有不同的行为在原始速度,内部和外部的碎片方面