学习-Redis开发和运维
2017-04-07 00:18:45 0 举报
AI智能生成
Redis开发和运维
作者其他创作
大纲/内容
Redis开发和运维
初步
特性
内存数据库,速度快
基于键值对的数据结构服务器
String
Bitmaps
HyperLogLog
Hash
List
Set
Ordered Set
丰富的功能
提供了键过期功能,用作缓存
发布订阅功能,实现消息系统
支持Lua脚本
简单事务支持
Pipeline,减少网络开销
简单稳定
客户端语言多
持久化
RDB
AOF
主从复制
高可用和分布式
Redis Sentinel
Redis Cluster
使用场景
缓存
排行榜系统
计数器
社交网络关系
消息队列
版本(第二位)
奇数-开发版本
偶数-稳定版本
命令行工具
redis-server
redis-cli
redis-benchmark
redis-check-aof
redis-check-dump
redis-sentinel
重要
Redis使用了单线程架构和I/O多路复用模型实现高性能的内存数据库
Redis是单线程命令处理的,面向快速执行场景的数据库
API基础
预备
全局命令
查看所有键 keys
当前数据库中的键总数 dbsize
检查键是否存在 exists
删除键 del
键过期 expire
键的数据结构类型 type
数据结构和内部编码
查看命令 object encoding
键管理
键重命名 rename
随机返回一个键 randomkey
键过期 expire/expireat
取消过期 persist
迁移键
把指定键从原数据库移动到目标数据库 move
实例间数据迁移 dump+restore
源数据库上dump将键值序列化为RDB格式
目标数据库使用restore恢复
非原子性,两个客户端连接分别执行
不支持多个键
migrate
支持多个键
原子性
集群用来实现水平扩容
遍历
全量遍历 keys
会造成堵塞,尽量少用
渐进式遍历 scan
时间复杂度为O(1)
缓解大量key的堵塞
不同数据类型提供了不同的命令
scan
hscan
sscan
zscan
注意:如果遍历过程中键发生变化,会出现缺失或者重复遍历的问题
数据库管理
默认16个数据库,集群只支持一个数据库0
命令
databases
select
flushdb
清除当前数据库
flushall
清除所有数据库
字符串
设置值 set
O(1)
获取值 get
删除 del
O(k),k是键的个数
批量设置值 mset
批量获取之 mget
计数 incr
追加 append
长度 strlen
设置并返回原值 getset
设置指定位置的字符 setrange
获取部分字符串 getrange
O(n),n是字符串长度
内部编码
int
embstr
raw
典型场景
计数
共享session
限速
哈希
hset
hget
hdel
hlen
hmget
hmset
hexists
hkeys
hvals
hgetall
hincrby
hstrlen
ziplist
节省内存
少量数据使用
hashtable
列表
元素有序
元素可以重复
lpush/rpush
O(k)
linsert
O(n)
lrange
O(s+n),s是start偏移量,n是start到end的范围
lindex
llen
lpop/rpop
lrem
ltrim
lset
blpop/brpop
堵塞版本的lpop/rpop
少量元素
linkedlist
双向链表
quicklist
3.2版本之后提供
文章列表
栈/队列
集合
sadd
srem
scard
sismember
srandmember
C(count)
spop
smembers
sinter
O(k*m),k是多个集合中元素最少的个数,m是键的个数
sunion
sdiff
intset
标签
无序
元素不重复
有序集合
有序
zadd
O(k*log(n))
zcard
zscore
zrank/zrevrank
O(log(n))
zrem
Zrange/zrevrange
O(log(n)+k)
zincrby
Zrangebyscore/zrevrangebyscore
zcount
zremrangebyrank
zremrangebyscore
zinterstore
O(n*k)+O(m*log(m)
zunionstore
O(n)+O(m*log(m))
skiplist
添加用户赞数
展示用户信息以及分数
进阶功能
慢查询分析
慢查询只统计“命令执行”阶段的时间
控制参数
slowlog-log-slower-than
默认10s判断是慢查询
slowlog-max-len
线上建议调大,可以记录更多的慢查询
获取慢查询日志
slowlog get
slowlog len
slowlog reset
Redis Shell
-r 命令执行多次
-i 每隔几秒执行一次命令
-x 从标准输入读取数据作为redis-cli的最后一个参数
-c 集群模式
-a 使用密码访问
--scan/--pattern 扫描指定模式的键
--slave 模拟成从节点,可以获取redis节点的更新操作
--rdb 请求Redis实例生成并发送RDB持久化文件,保存到本地
--raw/--noraw
使用--norow或者默认返回二进制
--pipe 将命令封装成Redis通信协议定义的数据格式,批量发送给Redis执行
--bigkeys 使用scan命令对键进行采样,找到占用内存比较大的
--eval 执行指定的Lua脚本
--latency 测试客户端到目标redis的网络延迟
--latency-history 分时段展示延迟信息
--latency-dist 以统计图表的形式展示延迟统计
--stat 实时获取Redis的重要统计信息
使用--row可以返回中文
-c 客户端的并发数量(默认50)
-n <requests> 客户端请求总量(默认 100000)
-t 对制定的命令进行基准测试
--csv 将结果输出为csv文件
Pipeline
原生批量命令(mget/mset等)是原子的,Pipeline是非原子的
原生批量命令一个命令对应多个key,Pipeline则支持多个命令
原生批量命令是Redis服务端支持实现的,Pipeline则需要服务端和客户端共同实现
事务与Lua
简单事务
multi
exec
discard
watch
监控key是否发生修改,如果发生修改,终止事务执行,忽略事务
如果watch的key在watch之后过期了,事务执行不受影响
在exec执行之后,watch的key会自动unwatch
处理机制
命令错误、语法错误:事务无法执行
运行时错误,事务照常执行,不支持回滚
本质:只是提供了一个原子操作而已,不支持回滚
Lua支持
执行方法
eval
evalsha
eval 脚本内容 key个数 key参数 参数列表
script load 加载外部脚本
script exists 判断sha1的指纹是否加载到了内存中
script flush 清楚所有已加载的脚本
script kill 杀掉正在执行的脚本
Lua API
redis.call
redis.pcall
使用基数算法利用极少内存空间完成独立总数统计
不完全可靠,存在一定误差率(大约0.81%的失误),基于概率
pfadd
pfcount
pfmerge
发布订阅
publish
subscribe/unsubscribe
psubscribe/punsubscribe
glob风格订阅
pubsub channels 查看活跃的频道
pubsub numsub 查看频道订阅数
pubsub numpat 查看模式的订阅数
缺点
无法收到频道订阅前的消息
GEO
客户端
通信协议
建立在TCP协议之上
Redis制定了RESP(REdis Serialization Protocol)实现客户端和服务端交互
发送命令格式
返回结果格式
状态回复 +
错误回复 -
整数回复 :
字符串回复 $
多条字符串回复 *
客户端管理
client list
id
addr
fd
name
qbuf/qbuf-free 输入缓冲区
为客户端发送命令到Redis执行命令提供了缓冲功能
某个客户端输入缓冲区达到1G,客户端将被关闭
输入缓冲区不受maxmemory控制
输出缓冲区
保存命令执行结果给客户端,为其提供缓冲
通过参数client-output-buffer-limit控制
分类
obl 固定缓冲区长度
oll 动态缓冲区列表长度
omem 使用的字节数
client setName/getName
client kill
client pause
monitor
用于监控Redis正在执行的命令
一旦并发量过大,monitor客户端的输出缓冲区会暴涨,可能瞬间占用大量内存
info clients
connected_clients:当前连接数
client_longest_output_list:当前输出缓冲区中队列对象个数最大值
client_bigest_input_buf:当前输入输出缓冲区中占用的最大容量
blocked_clients:正在执行堵塞命令的客户端个数
info stats
total_connections_received:启动以来处理的客户端总数
rejected_connections:启动以来拒绝的客户端连接数,重点监控
相关配置
timeout
maxclients
tcp-keepalive:周期性的检查关闭无效TCP连接
tcp-backlog
建议
禁止使用monitor命令,避免内存占用过大
限制输出缓冲区大小
优化
理解内存
内存消耗
内存使用统计 info memory
used_memory 内部存储所有数据内存占用量
used_memory_rss 操作系统角度显示Redis进程占用的物理内存总量
used_memory_peak 内存使用的最大值,标识used_memory的峰值
used_memory_lua Lua引擎消耗的内存大小
mem_fragmentation_ratio 内存碎片率
mem_allocator 内存分配器
自身内存
很小,一般可以忽略
对象内存
内存占用最大的一部分,存储用户的所有数据
缓冲内存
客户端缓冲
复制积压缓冲区
AOF缓冲区
内存碎片
内存管理
设置内存上限 maxmemory
动态调整内存上限 config set maxmemory
内存回收策略
删除过期键对象
内存达到maxmemory限制时触发内存溢出控制策略maxmemory-policy
内存优化
redisObject对象
type 对象使用的数据类型
encoding 对象的内部编码类型
lru 对象最后一次被访问的时间
refcount 对象被引用的次数
*ptr 对象数据(整型则直接存储,其它类型则为指针)
缩减键值对象长度
键值越短越好,但要能够区分业务
value要精简,去掉不必要的属性避免存储无效数据
共享对象池
开发中,在满足需求的情况下,尽可能使用整数对象以节省内存
共享对象池与maxmemory+LRU策略冲突,无法同时启用
字符串类型优化
内部使用了自己实现的字符串 SDS
字符串预分配,防止修改操作不断重分配内存和字节数据拷贝
字符串重构
编码优化
ziplist编码,节约内存,可以作为hash/list/zset的底层数据结构
intset编码,存储有序,不重复的整数集
配置优化
安全问题
bigkey
热点key
原理:将当前进程数据生成快照保存到硬盘
触发机制
手动
save命令
堵塞当前Redis服务器,直到完成
线上不建议使用
bgsave
fork子进程进行持久化
自动
使用配置:save m n,表示m秒内数据集存在n次修改时,自动触发bgsave
如果从节点执行全量复制,主节点自动执行bgsave生成RDB文件发送给从节点
执行debug reload命令重新加载时,自动触发save
默认情况下执行shutdown时,如果没有开启AOF,则自动执行bgsave
文件处理
保存
config set dir {newDir}
config set dbfilename {newFileName}
压缩
默认采用LZF算法进行压缩
config set rdbcompression {yes|no}
校验
使用redis-check-dump工具检测
优缺点
优点
RDB是一个紧凑的二进制文件,代表某个时间点上的数据快照,适合备份,全量复制
加载RDB恢复数据远远快于AOF方式
数据没办法实现实时持久化/秒级持久化
多版本RDB格式无法兼容
原理:以独立日志的方式记录每次的写命令,重启时执行AOF中的命令达到恢复的目的
使用AOF
appendonly yes
工作流程
append
写入命令追加到aof_buf
sync
硬盘同步
rewrite
随着AOF越来越大,需要定期对AOF文件进行重写,达到压缩的目的
load
重启时加载AOF文件恢复
命令写入
写入的内容直接是文本协议格式
追加到aof_buf中,写入缓冲区再同步到硬盘
文件同步
使用appendfsync参数控制
always
everysec(建议)
no
重写机制
手动触发 bgrewriteaof
自动触发
auto-aof-rewrite-min-size
auto-aof-rewrite-percentage
redis-check-aof --fix
复制
复制技术是Redis高可用的基础,主从复制是异步的
复制过程
建立
启动参数--slaveof {masterHost} {masterPort}
slaveof {masterHost} {masterPort}
断开
slaveof no one
安全性
requirepass
auth
默认从节点使用slave-read-only=yes配置为只读
传输延迟 repl-disable-tcp-nodelay
关闭:主从网络环境良好
开启:主从网络环境复杂,带宽紧张
拓扑
一主一从
主节点故障时从节点提供故障转移支持
重启主节点时先断开从节点与主节点的复制关系
一主多从
应用端可以利用多个从节点实现读写分离
避免从节点过多,会加重主节点的复制负担
树状主从
数据同步(使用psync命令)
类型
部分复制
全量复制
关键
复制偏移量
从节点维护自身偏移
上报主节点获取变更
复制积压缓冲区(repl_backlog)
保存在主节点上的一个固定长度的队列,默认为1M
保存最近已复制的数据,用于部分复制和复制命令丢失的数据补救
主节点运行ID
节点启动后动态分配的ID
用于唯一识别节点
重启后会改变,需要使用debug reload命令重启并保持ID不变
ID变更后会发生全量复制
心跳
心跳是主从双方都会发起的
主节点默认每10s发送给从节点ping
从节点每隔1s发送replconf ack {offset}命令给主
堵塞
内在原因
API/数据结构使用不当
slowlog get {n}分析慢查询日志
redis-cli --bigkeys 发现大对象
CPU饱和
单线程的redis处理命令时只能使用一个CPU
统计信息 redis-cli --stat
持久化堵塞
fork堵塞 info stats命令获取latest_fork_usec指标
AOF刷盘堵塞 info persistence中的aof_delayed_fsync指标
HugePage写操作堵塞
外在原因
CPU竞争
内存交换
网络问题
高可用
哨兵
集群
缓存设计
缓存更新策略
LRU/LFU/FIFO算法剔除
超时剔除
主动更新
最佳实践
低一致性业务建议配置最大内存和淘汰策略
高一致性业务结合超时剔除和主动更新
缓存粒度控制
通用性
空间占用
代码维护
缓存穿透
缓存空对象,设置较短的有效时间
布隆过滤器拦截
雪崩优化
保证缓存层服务高可用性
依赖隔离组件为后端限流并降级
提前演练
热点key重建
互斥锁
设置永远不过期
不设置过期时间
为value设置逻辑过期时间,单独线程更新缓存
收藏
0 条评论
回复 删除
下一页