Redis开发与运维
2019-07-08 11:34:14 8 举报
AI智能生成
Redis开发与运维
作者其他创作
大纲/内容
客户端
客户端通信协议RESP
发送命令格式
<div>*<参数数量>CRLF</div><div>$<参数1的字节数量>CRLF</div><div><参数1>CRLF</div><div>...</div><div>$<参数N的字节数量>CRLF</div><div><参数N> CRLF</div>
返回结果格式
状态恢复:第一个字节为"+"
错误回复:第一个字节为"-"
整数回复:第一个字节为":"
字符串回复:第一个字节为"$"
多条字符串回复:第一个字节为"*"
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节点
客户端常见异常
无法从连接池中获取到连接 <br>could not get a resource from the pool
高并发下连接池设置过小,出现供不应求
没有正确使用连接池,比如没有释放
存在慢查询操作,导致连接归还速度比较慢,造成连接池满
服务端异常造成客户端命令执行过程阻塞
客户端读写超时<br>read time out
读写超时时间设置过短
命令本身比较慢
网络不正常
redis阻塞
客户端连接超时<br>connect timed out
客户端缓存区异常<br>unexpected end of stream
输出缓存区满
长时间闲置连接被服务端主动断开
连接并发操作
lua脚本正在执行<br>BUSY redis is busy running a script
执行lua脚本并且超过了lua-time-limit
redis正在加载持久化<br>
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统计项对应的内存。<br>由于内存碎片率的存在,实际消耗的内存可能会比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(是否生成持久化文件)
小功能大用处
慢查询分析
注意点
慢查询只统计命令执行的时间,不包括命令排队以及网络时间<br>所以没有慢查询并不代表客户端没有超时
慢查询的两个配置参数
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 每隔几秒执行一次命令(<font color="#ff9999">单位为秒,但是数值可以为小数,可以做到每隔几毫秒执行命令</font>)
-x 从标准输入读取数据作为redis-cli的最后一个参数
-c 防止moved和ask异常
-a 密码
--scan 和 --pattern 扫描指定模式的键
--slave 将当前客户端模拟成当前redis节点的从节点
--rdb 请求redis实例生成并发送RDB持久化文件保存在本地,可用于定期备份
--pipe
--bigkeys 使用scan命令对redis的键进行采样,从中找到内存占用比较的的键值
-eval 指定指定的lua脚本
--latency 检测网络延迟<br>
--latency 测试客户端到目标redis的网络延迟
--latency-history 分时段的形式了解延迟信息<br>可以通过 -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<br>-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 列表 参数列表<br>如: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 脚本执行失败,则执行结束并返回 <br>redis.pcall 脚本执行失败,则忽略错误继续执行脚本
lua的好处
lua脚本在redis中是原子执行的
可以定制新的命令
多条命令打包,减少RTT
管理lua脚本
script load<br>script exists<br>script flush<br>script kill
lua_time_limt(默认为5s) lua脚本超时时间,当lua脚本执行时间超过该限制后,并不会停止执行lua脚本,<br>只会向其他正在执行的命令发送 BUSY 的信号,此时需要执行script kill 命令来杀死lua脚本。
当lua脚本正在执行写操作的时候,那么script kill 命令将不会生效,此时只能等待执行结束或者shutdown save 停掉redis服务
bitmaps
数据结构模型
本身不是一种数据结构,实际上就是字符串,但是可以对字符串的位进行操作
可以将bitmaps想象成一个以位为单位的数组,数组的每一个单元只能存储0和1,数组的下标叫做偏移量
命令
setbit key offset value<br>注意点:第一次初始化bitmaps时,如果偏移量很大,那么可能会阻塞redis
getbit key offset
bimaps间的操作 bitop op destkey key [key...]<br>操作支持 and ,or ,not ,xor(异或)
计算bitmaps中第一个值为targetBit的偏移量<br>bitops key targetBit [start] [end]
HyperLogLog
发布订阅
命令
发布消息 publish channel message
订阅消息 subscribe channel [channel ...]
取消订阅 unsubscribe [channel [channel ...]]
按照模式订阅和取消订阅<br>psubscribe pattern [patterb...]<br>punsubscribe [pattern [pattern ...]]
查看活跃的频道 pubsub channels [pattern]<br>查看频道订阅数 pubsub numsub [channel ...]<br>查看模式订阅数 pubsub numpat
GEO
持久化
RDB
触发机制
手动触发
save 阻塞redis服务器,知道RDB过程完成为止
bgsave 后台执行RDB操作<br>
自动触发
使用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重写目的
<span>降低了文件占用空间</span>
<span>更小的AOF文件可以更快地被Redis加载</span>
重写后AOF文件变小
<span>进程内已经超时的数据不再写入文件</span>
<span>旧的AOF文件含有无效命令</span>
<span>多条写命令可以合并为一个,如:lpush list a、lpush list b、lpush list c可以转化为:lpush list a b c</span>
触发时机
<span>手动触发</span>
<span>直接调用bgrewriteaof命令</span>
<span>自动触发</span>
<span>根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机。</span>
重写流程
重启加载
优先加载AOF文件
文件校验
<span>对于错误格式的AOF文件,先进行备份,然后采用redis-check-aof--fix命令进行修复,<br>修复后使用diff-u对比数据的差异,找出丢失的数据,有些可以人工修改补全</span>
阻塞
API的理解和使用
预备知识
全局命令
数据结构和内部编码
对应关系
好处
可以改进内部编码,而对外的数据结构和命令没有影响,<br>这样一旦开发出更优秀的内部编码,无需改动外部数据结构和命令
多种内部编码实现可以在不同场景下发挥各自的优势
单线程架构
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(栈)<br>lpush + rpop = Queue(队列)<br>lpush + ltrim = 有限集合<br>lpush + brpop = 消息队列
集合
命令
内部编码
intset(整数集合)
集合中的元素都是整数且元素个数小于set-max-intset-entries配置(默认512个)
hashtable(哈希表)
使用场景
标签功能
有序集合
列表,集合和有序集合异同点
命令
内部编码
ziplist(压缩列表)
有序集合的元素个数小于zset-max-ziplist-entries配置(默认128个)
每个元素的值都小于zset-max-ziplist-value配置(默认64字节)
skiplist(跳跃表)<br>
使用场景
排行榜
键管理
单个键管理
键重命名
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 条评论
下一页
为你推荐
查看更多