redis
redis
- 2016-01-12
- mikzzz
1.认识Redis
工作模型:单线程架构和IO多路复用来实现高性能的内存数据库服务
原因:a)单线程简化数据结构和算法的实现;b)避免线程切换和线程竞争的开销
应用场景:缓存/排行系统/统计器应用/社交网络/消息队列/热数据
2.数据类型
2-1.字符串类型
命令相关:使用mget可以减少网络次数,提高开发效率(字符串不能超过512MB)
内部编码:根据当前值的类型和长度决定使用哪种编码
int:8bytes长整型
embstr:小于等于39bytes的字符串
raw:大于39bytes的字符串
底层数据结构:数组
应用场景:缓存功能/计数/共享Seesion/限速
2-2.哈希类型
命令相关:键值本身又是一个键值对结构; set key field
内部编码:
ziplist压缩列表;满足哈希类型元素个数小于hash-max-ziplist-entries和所有值小于hash-max-ziplist-value
hashtable哈希表:当无法满足ziplist的条件时,会使用hashtable作为哈希的内部实现
底层数据结构:数组(hashkey) + 链表(field)
应用场景:关系数据表记录
2-3.列表类型
命令相关:可以根据索引查询修改,阻塞删除,头尾添加;根据不同的命令可以实现队列/栈等操作
内部编码:
ziplist压缩列表;满足哈希类型元素个数小于hash-max-ziplist-entries和所有值小于hash-max-ziplist-value
linkedlist链表:当无法满足ziplist的条件时,会使用linkedlist作为列表的内部实现
底层数据结构:双向链表
应用场景:消息队列/文章列表
2-4.集合
命令相关:一个集合中可以存放多个元素
内部编码:
intset整数集合:当集合中的元素个数小于set-max-intset-entries配置
hashtable哈希表;当集合类型无法满足intset条件
底层数据结构:hash
应用场景:标签功能
2-5.有序集合
命令相关:一个集合中可以存放多个拥有分数的元素,用于排序
内部编码:
ziplist压缩列表:当集合中的元素个数小于set-max-ziplist-entries配置
skiplist跳跃表;当集合类型无法满足ziplist条件时
底层数据结构:hash + 跳跃表
应用场景:排行系统
3.小功能
3-1.慢查询
配置方式:a)配置文件;b)动态配置(rewrite持久化到本地配置文件中)
获取慢查询日志:slowlog show get [n];采用队列存储,先进先出形式
日志属性:日志标识,发生时间,命令耗时,执行命令和参数
最佳实践:max-len > 1000 & slower-than 1ms
3-2.Pipeline
场景:将一组命令封装,通过一次RTT传输;能够减少网络延迟和性能瓶颈
Redis的批量命令与Pipeline区别:
原子性:批量命令是原子性的
命令格式:批量命令一次对应多个Key
实现机制:Pipeline需要客户端支持
最佳实践:可以将大Pipeline拆分成多个小Pipeline来完成
3-3.事务和Lua
事务:原子性,保证数据一致性
相关命令:multi开始事务,exec事务提交,discard停止事务;watch确保事务中的key没有被其他客户端修改
事务错误: a)语法错误:Redis事务忽略; b)运行错误:事务提交后执行报错
不支持回滚:保持Redis的简单快捷;关于语法错误而失败应该在开发过程中被发现
Lua脚本:Redis脚本语言
Lua脚本在Redis中是原子执行的,执行过程中不插入其他命令
Lua脚本定制命令并可以常驻内存中,实现复用的效果
Lua脚本可以将多条命令一次性打包,减少网络开销
3-4.Bitmaps和Hyperloglog
Bitmaps:一个以位为单位的数组,数组中的每个单元只能存储0和1,数组的下标称之为偏移量
设置:setbit key offset value
运算:bitop [and(交集) | or(并集) | not(非) | xor(异或)] destkey [keys…]
应用场景:大用户量时统计活跃数,能有效减少内存
Hyperloglog:一种基数算法,实际数据类型为字符串类型,利用极小的内存空间完成独立总数的统计(不需要单条记录)
3-5.发布和订阅
发布者客户端向指定的频道(channel)发布消 息,订阅该频道的每个客户端都可以收到该消息
相关命令:publish发布,subscrible订阅
注意点:a)客户端在执行订阅命令之后进入订阅状态;b)新开启的订阅客户端,无法接受到该频道之前的消息,因为Redis不会对发布的消息进行持久化
使用场景:聊天室/公告牌/消息解耦/视频管理系统
3-6.GEO
地理信息定位功能:支持存储地理位置信息来实现诸如附近位置、摇一摇这类依赖于地理位置信息的功能;底层实现是:zset
4.持久化
4-1.RDB方式
RDB持久化:把当前进程数据生成快照保存到硬盘的过程,触发RDB持久化分为手动触发和自动触发
手动触发:通过bgsave命令Redis进程执行fork操作创建子进程,由子进程负责完成
自动触发:
save相关配置: sava m n (表示m秒内数据集存在n次修改即自动触发bgsave)
从节点执行全量复制操作,主节点自动执行bgsave生成RDB文件并发送给从节点
执行debug reload命令重新加载Redis时,也会自动触发save操作
默认情况下执行shutdown命令时,如果没有开启AOF持久化功能则自动执行bgsave
执行流程:
RDB文件处理:保存和压缩并校验
RDB优点:
代表某个时间点的数据快照,适用备份和全量复制等场景
压缩的二进制文件,恢复“大数据集”效率较高
RDB缺点:
数据的实时持久化较差并且fork()操作会带来堵塞
特定的二进制文件会带来兼容性问题
4-2.AOF方式
AOF持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的,解决数据持久化的实时性
AOF工作流程:
1.命令写入以追加方式到AOF_buf
2.AOF缓冲区根据策略同步到AOF文件
3.随着AOF文件变大,需要定期对AOF文件进行重写,达到压缩目的
4.当Redis重启时,可以加载AOF文件进行数据恢复
命令写入追加到缓冲区的目的:
写入的内容是文件协议格式(1.兼容性;2.可读性;3.避免二次处理开销)
在性能和安全性方面做出平衡
同步策略:Redis提供多种AOF缓冲区同步文件策略,由appendfsync控制
always:调用write操作后并调用fsync保证AOF文件写入到磁盘中
no:调用write操作后,AOF文件同步到磁盘交由操作系统去实现
everysec:调用write操作后,由专门线程去每秒调用一次fsync
write操作:会触发延迟写机制,因为Linux在内核提供页缓冲区来提供磁盘IO性能;write操作在写入系统缓冲区后直接返回,同步硬盘依赖于系统调度机制
fsync操作:针对单个文件操作做强制硬盘同步,fsync将阻塞直到写入硬盘完成后返回,保证了数据持久化
重写机制:把Redis进程内的数据转化为命令同步到新AOF文件的过程,这个过程会让AOF文件体积变小,从而提高恢复时的效率
1.进程已经超时的数据不再写入新文件
2.通过进程内数据直接生成,避免旧文件中的无效命令
3.多条命令可以合并为一个
AOF重写触发方式:
手动触发:执行bgrewriteaof命令
自动触发:同时满足以下2个条件
1.auto-aof-rewrite-min-size:表示运行AOF重写时文件最小体积,默认为64MB
2.auto-aof-rewrite-percentage:表示当前AOF文件空间和上一次重写后AOF文件空间的比值
AOF重写工作流程
Redis持久化加载流程
AOF持久化开启时且存在AOF文件时,优先加载AOF文件
AOF关闭或者AOF文件不存在时,加载RDB文件
加载AOF/RDB文件成功后,Redis启动成功
AOF/RDB文件存在错误时,Redis启动失败
关于AOF文件异常
损坏的文件Redis服务会拒绝启动(可以通过redis-check-aof-fix命令修复后,进行对比并进行手工修改补全)
结尾不挖完整的文件Redis服务忽略并继续启动,同时打印报警信息
AOF追加阻塞:当开启AOF持久化时,常用的同步磁盘策略是everysec,对于这种方式,Redis会使用同步条线程每秒执行fsync同步硬盘,当系统硬盘资源繁忙时,会造成Redis主线程阻塞
everysec刷盘策略过程:
1.同步线程负责每秒调用fsync操作进行同步磁盘
2.主进程会去对比上次fsync同步时间,如果在2s内则通过,否则会堵塞(磁盘资源紧张)
3.everysec策略最多可能丢失2s数据;如果系统fsync缓慢,会导致主进程堵塞
AOF优点:
实时备份:能够到秒级
以appen-only的模式写入:没有磁盘寻址开销,写入性能较高
可读性强:具有更灵活的处理方式
AOF缺点:
相同的数据集:AOF文件会比RDB文件大
Redis高负载情况下:RDB会拥有更好的性能保证
数据恢复:比较慢并不适合全量备份
5.安全建议
根据具体网络环境决定是否设置Redis密码
rename-command可以伪装命令,但是要注意成本
合理的防火墙是防止攻击的利器
bind可以将Redis的访问绑定到指定网卡上
定期备份数据应该作为习惯性操作
可以适当错开Redis默认端口启动
使用非root用户启动Redis