Redis开发与运维
2019-07-08 11:34:14 8 举报
AI智能生成
Redis开发与运维
作者其他创作
大纲/内容
客户端
客户端通信协议RESP
发送命令格式
*<参数数量>CRLF
$<参数1的字节数量>CRLF
<参数1>CRLF
...
$<参数N的字节数量>CRLF
<参数N> CRLF
返回结果格式
状态恢复:第一个字节为"+"
错误回复:第一个字节为"-"
整数回复:第一个字节为":"
字符串回复:第一个字节为"$"
多条字符串回复:第一个字节为"*"
Java客户端Jedis
jedis对象池参数
客户端管理
客户端API
client list
注意点
输入缓冲区
输入缓冲区最大为1G,且不能配置
输入缓冲区超过1G,客户端将会被关闭
输入缓冲区不受maxmemory控制
输入缓冲区过大原因
redis处理速度跟不上输入缓冲区的输入速度,并且输入缓存冲区中包含了大量的bigkey
redis发生阻塞,造成客户端输入的命令积压
输出缓冲区
输出缓冲区由固定缓冲区和动态缓冲区组成
client setNmae 和 client getName
杀掉制定ip和port的客户端 client kill ip:port
可以手动杀掉长时间idle的客户端(timeout设置为0)
手动处理异常客户端,如使用了monitor命令导致输出客户端缓存变大的客户端
阻塞客户端timeout毫秒数 client pause timeout(毫秒)
client pause 只对普通客户端和发布订阅客户端有效,对主从复制无效,所以可以 使用该命令来使主从一致
可以以一种可控的方式来使得客户端连接从一个redis节点切换到另一个redis节点
客户端常见异常
无法从连接池中获取到连接
could not get a resource from the pool
could not get a resource from the pool
高并发下连接池设置过小,出现供不应求
没有正确使用连接池,比如没有释放
存在慢查询操作,导致连接归还速度比较慢,造成连接池满
服务端异常造成客户端命令执行过程阻塞
客户端读写超时
read time out
read time out
读写超时时间设置过短
命令本身比较慢
网络不正常
redis阻塞
客户端连接超时
connect timed out
connect timed out
客户端缓存区异常
unexpected end of stream
unexpected end of stream
输出缓存区满
长时间闲置连接被服务端主动断开
连接并发操作
lua脚本正在执行
BUSY redis is busy running a script
BUSY redis is busy running a script
执行lua脚本并且超过了lua-time-limit
redis正在加载持久化
redis使用的内存超过maxmemory配置
客户端连接数过大
复制
理解内存
理解内存
内存消耗
内存使用统计
mem_fragmentation_ratio >1 时,说明多出的部门内存没有用于数据存储,而是被内存碎片所消耗
mem_fragmentation_ratio <1 时,这种情况一般出现在操作系统把redis内存swap到硬盘所致
内存消耗划分
自身内存
对象内存
缓冲内存
客户端缓冲
输入缓冲区无法控制,最大为1G
输出缓冲区通过参数client-output-buffer-limit控制
复制积压缓冲区
可用于表面全量复制
AOF缓冲区
保存redis在重写期间保存的最近的写入命令
内存碎片
原因
频繁做更新操作
大量过期键删除
解决方案
数据对齐
安全重启
子进程内存消耗
子进程消耗主要指执行AOF/RDB重写时redis创建的子进程消耗
内存管理
设置内存上限
目的
用户缓存场景,超出内存上限时使用LRU等策略来释放空间
防止所用内存超过服务器物理内存
注意点
maxmemory限制的是redis实际使用的内存量,也就是used_memory统计项对应的内存。
由于内存碎片率的存在,实际消耗的内存可能会比maxmemory设置的更大
由于内存碎片率的存在,实际消耗的内存可能会比maxmemory设置的更大
动态调整内存上限
config set maxmemory
内存回收策略
删除过期键对象
惰性删除
定时任务删除
内存溢出控制策略(maxmemory-policy)
noeviction:默认策略,不会删除任何数据,拒绝所有写入并返回客户端错误信息
volatile-lru:根据lru算法删除设置了超时属性的键,直到腾出足够空间。如果没有课删除的键对象,则回退到noeviction策略
allkeys-lru:根据lru算法删除键,不管数据有没有设置超时属性,直到腾出足够空间为止
allkeys-random:随机删除所有键,直到腾出足够空间为止
volatile-random:随机删除过期键,直到腾出足够空间为止
volatile-ttl:根据键对象的 ttl属性,删除最近将要过期数据,如果没有,则回退到noeviction策略
初识Redis
Redis特性
速度快
基于内存
c语言实现
单线程架构避免多线程竞争
Redis源代码精打细磨
基于键值对的数据结构服务器
功能丰富
简单稳定
客户端语言多
持久化
主从复制
高可用和分布式
Redis使用场景
缓存
排行榜系统
计数器应用
社交网络
消息队列系统
Redis安装
Linux下安装
源代码安装
Redis基本操作
启动
#redis-server /opt/redis/redis.conf
命令行客户端
交互方式
redis-cli -h {host} -p {port}
命令方式
redis-cli -h {host} -p {port} {command}
注意点
默认host是本机,即127.0.0.1
默认端口号6379
停止Redis服务
redis-cli shutdown nosave|save(是否生成持久化文件)
小功能大用处
慢查询分析
注意点
慢查询只统计命令执行的时间,不包括命令排队以及网络时间
所以没有慢查询并不代表客户端没有超时
所以没有慢查询并不代表客户端没有超时
慢查询的两个配置参数
slowlog-log-slower-than
slowlog-max-len
命令
slowlog get [n]
slowlog len
slowlog reset
最佳实践
slowlog-max-len线上建议调大慢查询队列
slowlog-log-slower-than 高QPS场景下建议配置为毫秒
客户端超时,需要检查该时间点是否有对应的慢查询,从而分析出是否为慢查询导致的命令级联阻塞
定期执行slow get 命令将慢查询日志持久化
Redis shell
redis-cli
-r 命令执行多次
-i 每隔几秒执行一次命令(单位为秒,但是数值可以为小数,可以做到每隔几毫秒执行命令)
-x 从标准输入读取数据作为redis-cli的最后一个参数
-c 防止moved和ask异常
-a 密码
--scan 和 --pattern 扫描指定模式的键
--slave 将当前客户端模拟成当前redis节点的从节点
--rdb 请求redis实例生成并发送RDB持久化文件保存在本地,可用于定期备份
--pipe
--bigkeys 使用scan命令对redis的键进行采样,从中找到内存占用比较的的键值
-eval 指定指定的lua脚本
--latency 检测网络延迟
--latency 测试客户端到目标redis的网络延迟
--latency-history 分时段的形式了解延迟信息
可以通过 -i 参数来控制间隔时间
可以通过 -i 参数来控制间隔时间
--latency-dist 以统计图表的形式从控制台输出延迟统计信息
--stat 获取redis的统计信息
--raw 和 --no-raw
redis-server
redis-server --test-memory 1024
redis-benchmark
-c 并发量(默认为50)
-n 客户端请求总量
-q 仅仅显示requests per second 信息
-r 产生随机键
redis-benchmark -c 100 -n 20000 -r 10000
-r 10000 表示只对后四位做随机处理(-r 不是随机数的个数)
-r 10000 表示只对后四位做随机处理(-r 不是随机数的个数)
-p 每个请求pipline的数据量
-t 对指定命令进行基准测试
redis-benchmark -t get,set -q 只对set和get命令进行测试
--csv 将结果按照CSV格式输出
pipeline
好处:减少RTT
最佳实践
每次Pipline组装的命令不宜过多,否则会增加客户端的等待实践以及造成一定的网路阻塞
事务与lua
事务
命令
multi 开始事务 exec 结束事务 discard 停止事务
错误处理
命令错误:如语法错误,导致事务不执行
运行时错误:如sadd错写为zadd,redis不会回滚事务
lua
lua的用法
eval 脚本内容 key 个数 key 列表 参数列表
如:eval 'return "hello" .. KEYS[1] .. ARGV[1]' 1 redis world
如:eval 'return "hello" .. KEYS[1] .. ARGV[1]' 1 redis world
evalsha
加载脚本 script load "${cat lua_get.lua}"
执行脚本 evalsha 脚本SHA1值 key个数 key列表 参数列表
redis api与lua
redis.call 脚本执行失败,则执行结束并返回
redis.pcall 脚本执行失败,则忽略错误继续执行脚本
redis.pcall 脚本执行失败,则忽略错误继续执行脚本
lua的好处
lua脚本在redis中是原子执行的
可以定制新的命令
多条命令打包,减少RTT
管理lua脚本
script load
script exists
script flush
script kill
script exists
script flush
script kill
lua_time_limt(默认为5s) lua脚本超时时间,当lua脚本执行时间超过该限制后,并不会停止执行lua脚本,
只会向其他正在执行的命令发送 BUSY 的信号,此时需要执行script kill 命令来杀死lua脚本。
只会向其他正在执行的命令发送 BUSY 的信号,此时需要执行script kill 命令来杀死lua脚本。
当lua脚本正在执行写操作的时候,那么script kill 命令将不会生效,此时只能等待执行结束或者shutdown save 停掉redis服务
bitmaps
数据结构模型
本身不是一种数据结构,实际上就是字符串,但是可以对字符串的位进行操作
可以将bitmaps想象成一个以位为单位的数组,数组的每一个单元只能存储0和1,数组的下标叫做偏移量
命令
setbit key offset value
注意点:第一次初始化bitmaps时,如果偏移量很大,那么可能会阻塞redis
注意点:第一次初始化bitmaps时,如果偏移量很大,那么可能会阻塞redis
getbit key offset
bimaps间的操作 bitop op destkey key [key...]
操作支持 and ,or ,not ,xor(异或)
操作支持 and ,or ,not ,xor(异或)
计算bitmaps中第一个值为targetBit的偏移量
bitops key targetBit [start] [end]
bitops key targetBit [start] [end]
HyperLogLog
发布订阅
命令
发布消息 publish channel message
订阅消息 subscribe channel [channel ...]
取消订阅 unsubscribe [channel [channel ...]]
按照模式订阅和取消订阅
psubscribe pattern [patterb...]
punsubscribe [pattern [pattern ...]]
psubscribe pattern [patterb...]
punsubscribe [pattern [pattern ...]]
查看活跃的频道 pubsub channels [pattern]
查看频道订阅数 pubsub numsub [channel ...]
查看模式订阅数 pubsub numpat
查看频道订阅数 pubsub numsub [channel ...]
查看模式订阅数 pubsub numpat
GEO
持久化
RDB
触发机制
手动触发
save 阻塞redis服务器,知道RDB过程完成为止
bgsave 后台执行RDB操作
自动触发
使用save先关配置,如'save m n '
从节点执行全量复制操作
执行debug reload命令重新加载redis时,也会自动触发save操作
默认情况下执行shutdown命令时,如果没有开启AOF持久化功能则自动执行bgsave
流程说明
RDB优缺点
优点
RDB是紧凑压缩的二进制文件,可用于备份,全量复制场景
redis加载RDB恢复数据远远快于AOF
缺点
无法实时/秒级持久化
RDB文件版本兼容问题
子主题
AOF
使用AOF
appendonly yes开启aof
AOF工作流程
命令写入
将redis命令以文本格式写入到aof文件中
文件同步
重写机制
AOF重写目的
降低了文件占用空间
更小的AOF文件可以更快地被Redis加载
重写后AOF文件变小
进程内已经超时的数据不再写入文件
旧的AOF文件含有无效命令
多条写命令可以合并为一个,如:lpush list a、lpush list b、lpush list c可以转化为:lpush list a b c
触发时机
手动触发
直接调用bgrewriteaof命令
自动触发
根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机。
重写流程
重启加载
优先加载AOF文件
文件校验
对于错误格式的AOF文件,先进行备份,然后采用redis-check-aof--fix命令进行修复,
修复后使用diff-u对比数据的差异,找出丢失的数据,有些可以人工修改补全
修复后使用diff-u对比数据的差异,找出丢失的数据,有些可以人工修改补全
阻塞
API的理解和使用
预备知识
全局命令
数据结构和内部编码
对应关系
好处
可以改进内部编码,而对外的数据结构和命令没有影响,
这样一旦开发出更优秀的内部编码,无需改动外部数据结构和命令
这样一旦开发出更优秀的内部编码,无需改动外部数据结构和命令
多种内部编码实现可以在不同场景下发挥各自的优势
单线程架构
IO多路复用单线程架构
字符串
命令
内部编码
int:8个字节的长整型
embstr:小于等于39个字节的字符串
raw:大于39个字节的字符串
典型使用场景
缓存
计数
共享session
限速
哈希
命令
内部编码
ziplist(压缩列表)
哈希类型元素小于hash-max-ziplist-entries配置(默认512)
所有值都小于hash-max-ziplist-value配置(默认64)
hashtable(哈希表)
使用场景
映射实体属性
列表
命令
内部编码
ziplist(压缩列表)
当列表的元素个数小于list-max-ziplist-entries配置(默认512个)
列表中每个元素的值都小于list-max-ziplist-value配置时(默认64字节)
linkedlist(链表)
使用场景
消息队列
文章列表
使用口诀
lpush + lpop = Stack(栈)
lpush + rpop = Queue(队列)
lpush + ltrim = 有限集合
lpush + brpop = 消息队列
lpush + rpop = Queue(队列)
lpush + ltrim = 有限集合
lpush + brpop = 消息队列
集合
命令
内部编码
intset(整数集合)
集合中的元素都是整数且元素个数小于set-max-intset-entries配置(默认512个)
hashtable(哈希表)
使用场景
标签功能
有序集合
列表,集合和有序集合异同点
命令
内部编码
ziplist(压缩列表)
有序集合的元素个数小于zset-max-ziplist-entries配置(默认128个)
每个元素的值都小于zset-max-ziplist-value配置(默认64字节)
skiplist(跳跃表)
使用场景
排行榜
键管理
单个键管理
键重命名
rename key newkey (强制重命名)
renamenx key newkey(如果newkey已经存在则不生效)
随机返回一个键
randomkey
键过期
秒为单位
expire key seconds
expireat key timestamp
毫秒为单位
pexpire key milliseconds
pexpireat key milliseconds-timestamp
查询剩余时间 ttl pttl
清除过期时间
persist key
注意点
执行set命令会去掉过期时间
Redis不支持二级数据机(如哈希,列表)构内部元素的过期功能
setex = set +expire
迁移键
move key db(把指定的键从源数据库迁移到目标数据库)
dump + restore
在源Redis上执行dump命令将键值序列化,格式为RDB
在目标Redis上restore命令将上面序列化的值进行复原
migrate
migrate host port key|"" destination-db timeout [copy] [replace] [keys key [key ...]]
命令比较
遍历键
全量遍历键 keys pattern
渐进式遍历 scan cursor [match pattern] [count number]
数据库管理
切换数据库 select dbIndex
清除数据库 flushdb/flushall
0 条评论
下一页