页面“Shell基础”与“Redis常用操作”之间的差异
第1行: | 第1行: | ||
− | == | + | |
+ | [[Redis运维]] | ||
+ | |||
+ | =清理= | ||
+ | |||
+ | [[Redis批量删除key]] | ||
+ | |||
+ | redis-cli -h 192.168.10.213 -c -p 7004 -a passwD9923 KEYS "dict_telegram_group_telegram_group_share_id" | xargs -I {} redis-cli -h 192.168.10.213 -c -p 7004 -a passwD9923 del {} | ||
+ | |||
+ | =usage= | ||
+ | |||
+ | redis基本命令 String | ||
+ | |||
+ | <pre> | ||
+ | |||
+ | 非交互 redis-cli -h -p youcommand | ||
+ | |||
+ | redis-cli -h 127.0.0.1 | ||
+ | 127.0.0.1:6379> Auth upassword | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | set hey you | ||
+ | |||
+ | set love you | ||
+ | |||
+ | redis> SET key1 "Hello" | ||
+ | "OK" | ||
+ | redis> SET key2 "World" | ||
+ | "OK" | ||
+ | redis> DEL key1 key2 key3 | ||
+ | (integer) 2 | ||
+ | |||
+ | |||
+ | |||
+ | keys * | ||
+ | </pre> | ||
+ | https://redis.io/commands/del | ||
+ | |||
+ | |||
+ | <pre> | ||
+ | SETEX 命令的效果和以下两个命令的效果类似: | ||
+ | |||
+ | SET key value | ||
+ | EXPIRE key seconds # 设置生存时间 | ||
+ | |||
+ | SETEX 和这两个命令的不同之处在于 SETEX 是一个原子(atomic)操作, 它可以在同一时间内完成设置值和设置过期时间这两个操作, 因此 SETEX 命令在储存缓存的时候非常实用。 | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | </pre> | ||
+ | ==usage from 运维开发与运维== | ||
+ | <pre> | ||
+ | |||
+ | 创建新列表 | ||
+ | |||
+ | 127.0.0.1:6379> rpush listkey c java b a | ||
+ | (integer) 4 | ||
+ | |||
+ | #查看列表 -1 就是所有 了 | ||
+ | 127.0.0.1:6379> lrange listkey 0 -1 | ||
+ | 1) "c" | ||
+ | 2) "java" | ||
+ | 3) "b" | ||
+ | 4) "a" | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | 2.4.1 | ||
+ | 1 添加操作 | ||
+ | |||
+ | #在 b前插入java | ||
+ | 127.0.0.1:6379> linsert listkey before b java | ||
+ | (integer) 0 | ||
+ | 127.0.0.1:6379> lrange listkey 0 -1 | ||
+ | |||
+ | |||
+ | 2.查找 | ||
+ | |||
+ | 2 到 4 | ||
+ | 127.0.0.1:6379> lrange listkey 1 3 | ||
+ | 1) "java" | ||
+ | 2) "b" | ||
+ | 3) "a" | ||
+ | |||
+ | |||
+ | |||
+ | 127.0.0.1:6379> lrange listkey 1 3 | ||
+ | 1) "java" | ||
+ | 2) "b" | ||
+ | 3) "a" | ||
+ | |||
+ | 3.删除 | ||
+ | lpop key | ||
+ | |||
+ | (1) 左弹出 | ||
+ | 127.0.0.1:6379> lpop listkey | ||
+ | "c" | ||
+ | |||
+ | 右弹出 | ||
+ | rpop key | ||
+ | |||
+ | (3)删除指定元素 | ||
+ | |||
+ | |||
+ | 127.0.0.1:6379> lrem listkey 4 a #删除左开始的4个为a的元素 | ||
+ | (integer) 1 | ||
+ | |||
+ | (4) | ||
+ | |||
+ | |||
+ | 127.0.0.1:6379> lrange listkey 0 -1 | ||
+ | 1) "c" | ||
+ | 2) "java" | ||
+ | 3) "b" | ||
+ | 127.0.0.1:6379> ltrim listkey 1 3 #1 到3 被删除了 | ||
+ | OK | ||
+ | 127.0.0.1:6379> lrange listkey 0 -1 | ||
+ | 1) "java" | ||
+ | 2) "b" | ||
+ | |||
+ | 4.修改 | ||
+ | #把第三个改为python | ||
+ | 127.0.0.1:6379> rpush listkey c java b a | ||
+ | (integer) 4 | ||
+ | 127.0.0.1:6379> lset listkey 2 python | ||
+ | OK | ||
+ | |||
+ | 5 阻塞操作 | ||
+ | blpop | ||
+ | brpop | ||
+ | |||
+ | 2.4.2 内部编码 | ||
+ | </pre> | ||
+ | |||
+ | ===2.5 集合=== | ||
+ | <pre> | ||
+ | 2.5.1 命令 | ||
+ | |||
+ | |||
+ | (1) add | ||
+ | 27.0.0.1:6379> exists myset | ||
+ | (integer) 0 | ||
+ | 127.0.0.1:6379> sadd myset a b c | ||
+ | (integer) 3 | ||
+ | 127.0.0.1:6379> sadd myset a b | ||
+ | (integer) 0 | ||
+ | |||
+ | (2) del | ||
+ | 127.0.0.1:6379> srem myset a b | ||
+ | (integer) 2 | ||
+ | |||
+ | (3) count | ||
+ | 127.0.0.1:6379> scard myset | ||
+ | (integer) 1 | ||
+ | |||
+ | (4) exists | ||
+ | |||
+ | |||
+ | 127.0.0.1:6379> sismember myset c | ||
+ | (integer) 1 | ||
+ | |||
+ | (5)随机 | ||
+ | 127.0.0.1:6379> sadd myset a b c | ||
+ | (integer) 2 | ||
+ | 127.0.0.1:6379> srandmember myset 2 | ||
+ | 1) "a" | ||
+ | 2) "b" | ||
+ | |||
+ | (6) | ||
+ | |||
+ | 127.0.0.1:6379> spop myset | ||
+ | "a" | ||
+ | 127.0.0.1:6379> srandmember myset 2 | ||
+ | 1) "c" | ||
+ | 2) "b" | ||
+ | |||
+ | 7)取得所有 | ||
+ | 127.0.0.1:6379> smembers myset | ||
+ | 1) "c" | ||
+ | 2) "b" | ||
+ | |||
+ | 2.集合间操作 | ||
+ | |||
+ | 2.集合间操作 | ||
+ | |||
+ | 127.0.0.1:6379> SADD user:1:follow it music his sports | ||
+ | (integer) 4 | ||
+ | 127.0.0.1:6379> SADD user:2:follow it music his sports | ||
+ | (integer) 4 | ||
+ | |||
+ | 交集 | ||
+ | 127.0.0.1:6379> sinter user:1:follow user:2:follow | ||
+ | 1) "sports" | ||
+ | 2) "it" | ||
+ | |||
+ | 并集 | ||
+ | 127.0.0.1:6379> sunion user:1:follow user:2:follow | ||
+ | 1) "sports" | ||
+ | 2) "his" | ||
+ | 3) "music" | ||
+ | |||
+ | (4) 结果保存 | ||
+ | |||
+ | |||
+ | 4) "it" | ||
+ | |||
+ | 127.0.0.1:6379> sdiff user:1:follow user:2:follow | ||
+ | |||
+ | |||
+ | 2.5.2 内部编码 | ||
+ | |||
+ | 127.0.0.1:6379> sadd setkey 1 2 3 4 | ||
+ | (integer) 4 | ||
+ | 127.0.0.1:6379> object encoding setkey | ||
+ | "intset" | ||
+ | |||
+ | 2.5.3 使用场景 | ||
+ | </pre> | ||
+ | === 2.6 有序集合=== | ||
+ | <pre> | ||
+ | 2.6.1 | ||
+ | |||
+ | # | ||
+ | 127.0.0.1:6379> zadd user:ranking 251 tom | ||
+ | (integer) 1 | ||
+ | |||
+ | 27.0.0.1:6379> zadd user:ranking 1 kris 91 mike 220 frank 220 tim 250 martin | ||
+ | (integer) 5 | ||
+ | |||
+ | |||
+ | 127.0.0.1:6379> zcard user:ranking | ||
+ | (integer) 6 | ||
+ | |||
+ | 127.0.0.1:6379> zscore user:ranking tom | ||
+ | "251" | ||
+ | |||
+ | |||
+ | 排名 | ||
+ | 127.0.0.1:6379> zrank user:ranking tom | ||
+ | (integer) 5 | ||
+ | 127.0.0.1:6379> zrevrank user:ranking tom | ||
+ | (integer) 0 | ||
+ | |||
+ | 删除成员 | ||
+ | 127.0.0.1:6379> zrem user:ranking mike | ||
+ | (integer) 1 | ||
+ | |||
+ | 加了9分 | ||
+ | 127.0.0.1:6379> zincrby user:ranking 9 tom | ||
+ | "260" | ||
+ | |||
+ | (7)返回指定排名范围的成员 | ||
+ | |||
+ | 127.0.0.1:6379> zrange user:ranking 0 2 withscores | ||
+ | 1) "kris" | ||
+ | 2) "1" | ||
+ | 3) "mike" | ||
+ | 4) "91" | ||
+ | 5) "frank" | ||
+ | 6) "200" | ||
+ | 127.0.0.1:6379> zrevrange user:ranking 0 2 withscores | ||
+ | 1) "tom" | ||
+ | 2) "251" | ||
+ | 3) "martin" | ||
+ | 4) "250" | ||
+ | 5) "tim" | ||
+ | 6) "220" | ||
+ | |||
+ | 8)返回指定分数范围的成员 | ||
+ | 127.0.0.1:6379> zrangebyscore user:ranking (200 +inf withscores | ||
+ | 1) "tim" | ||
+ | 2) "220" | ||
+ | 3) "martin" | ||
+ | 4) "250" | ||
+ | 5) "tom" | ||
+ | 6) "251" | ||
+ | |||
+ | |||
+ | (9)返回指定分数范围成员个数 | ||
+ | |||
+ | 返回200到221分的成员的个数 | ||
+ | 127.0.0.1:6379> zcount user:ranking 200 221 | ||
+ | (integer) 2 | ||
+ | |||
+ | 10)删除指定排名内的升序元素 | ||
+ | |||
+ | |||
+ | 2.6.1 2019年 8月23日 星期五 14时41分48秒 CST | ||
+ | |||
+ | 2.集合间的操作 | ||
+ | 两个有序集合导入到Redis中 | ||
+ | zadd user:ranking:1 1 kris 91 mike 200 frank 220 tim 250 martin | ||
+ | zadd user:ranking:2 8 james 77 mike 625 martin 888 tom | ||
+ | |||
+ | Redis DEL 命令 | ||
+ | > DEL KEY_NAME | ||
+ | |||
+ | </pre> | ||
+ | [https://www.redis.net.cn/order/3528.html Redis DEL 命令 - 该命令用于在 key 存在是删除 key] | ||
+ | |||
+ | ==2.7 键管理 == | ||
+ | ===2.7.1 单个键管理 === | ||
+ | <pre> | ||
+ | 2019年 8月31日 星期六 16时03分38秒 CST | ||
+ | |||
+ | |||
+ | 1.key rename | ||
+ | rename key newkey | ||
+ | renamenx 比较安全 | ||
+ | 127.0.0.1:6379> get evan | ||
+ | "36" | ||
+ | 127.0.0.1:6379> rename evan eva | ||
+ | OK | ||
+ | 127.0.0.1:6379> get eva | ||
+ | "36" | ||
+ | 127.0.0.1:6379> get evan | ||
+ | (nil) | ||
+ | |||
+ | 2.随机返回 | ||
+ | randomkey | ||
+ | |||
+ | 3.key 过期 2019年 9月 1日 | ||
+ | |||
+ | 127.0.0.1:6379> set hello world | ||
+ | OK | ||
+ | 127.0.0.1:6379> expire hello 10 | ||
+ | (integer) 1 | ||
+ | 127.0.0.1:6379> ttl hello | ||
+ | (integer) 1 | ||
+ | 127.0.0.1:6379> ttl hello | ||
+ | (integer) -2 | ||
+ | |||
+ | 4.key 迁移 | ||
+ | |||
+ | (1) move 不用 知道就行了 | ||
+ | (2)dump + restore | ||
+ | |||
+ | (3)migrate | ||
+ | |||
+ | |||
+ | </pre> | ||
+ | |||
+ | ===2.7.2 遍历键 === | ||
+ | <pre> | ||
+ | key partern | ||
+ | |||
+ | get | ||
+ | key * | ||
+ | |||
+ | 2.渐进式子 | ||
+ | |||
+ | scan | ||
+ | |||
+ | </pre> | ||
+ | ===2.7.3 数据库管理 === | ||
+ | <pre> | ||
+ | 1.切换 select 默认是 0 | ||
+ | |||
+ | 127.0.0.1:6379[2]> set hello love | ||
+ | OK | ||
+ | 127.0.0.1:6379[2]> SELECT 3 | ||
+ | OK | ||
+ | 127.0.0.1:6379[3]> get hello | ||
+ | (nil) | ||
+ | |||
+ | |||
+ | 2.flushdb flushall | ||
+ | |||
+ | flushall 全部数据不见了 | ||
+ | </pre> | ||
+ | [https://www.cnblogs.com/Cherry-Linux/p/8046276.html Redis键迁移] | ||
+ | |||
+ | =Chpater 3 = | ||
+ | |||
+ | ==慢查询分析== | ||
+ | [https://blog.csdn.net/sunhuiliang85/article/details/74800001 redis-慢查询分析] | ||
+ | |||
+ | ==redis shell== | ||
+ | <pre> | ||
+ | redis-cli | ||
+ | -r | ||
+ | evan@latop:~$ redis-cli -r 3 ping | ||
+ | PONG | ||
+ | PONG | ||
+ | PONG | ||
+ | |||
+ | evan@latop:~$ redis-cli -r 3 -i 1 ping | ||
+ | PONG | ||
+ | PONG | ||
+ | PONG | ||
+ | |||
+ | evan@latop:~$ echo "world" |redis-cli -x set hello | ||
+ | 127.0.0.1:6379> get hello | ||
+ | "world\n" | ||
+ | |||
+ | -c cluster | ||
+ | |||
+ | -a (auth) | ||
+ | |||
+ | 6.--scan and --pattern | ||
+ | |||
+ | 7 --slave | ||
+ | |||
+ | 8 --rdb | ||
+ | |||
+ | 12 -- latency | ||
+ | |||
+ | 13 --stat 实时 比info 简单些 | ||
+ | |||
+ | redis-cli --stat | ||
+ | ------- data ------ --------------------- load -------------------- - child - | ||
+ | keys mem clients blocked requests connections | ||
+ | 1 838.51K 1 0 5 (+0) 2 | ||
+ | 1 838.51K 1 0 6 (+1) 2 | ||
+ | 1 838.51K 1 0 7 (+1) 2 | ||
+ | |||
+ | 14 --no-raw 原始格式 | ||
+ | --raw 格式化过 | ||
+ | |||
+ | 127.0.0.1:6379> set evan "你�好" | ||
+ | OK | ||
+ | 127.0.0.1:6379> get evan | ||
+ | "\xe4\xbd\xa0\xe5\x8f\xe5\xa5\xbd" | ||
+ | |||
+ | redis-cli --raw get evan | ||
+ | 你�好 | ||
+ | |||
+ | 3.2.2 redis-server --test-memory 1024 | ||
+ | </pre> | ||
+ | |||
+ | =Chpater 5 持久化 = | ||
+ | <pre> | ||
+ | |||
+ | redis的存储功能只是用做备份,恢复的功能,全量数据还是存储在内存中。 | ||
+ | redis内部提供了两种固化数据的方式,aof 和rdb。 | ||
+ | |||
+ | 运维提示 | ||
+ | 当硬盘坏或者 写满时 可以 config set dir {newDir} 在线修改文件路径 到可用的磁盘 再执行bgsave 同样可以用于aof | ||
+ | |||
+ | 5.2 AOF | ||
+ | |||
+ | |||
+ | 5.2.1 使用AOF | ||
+ | 开启AOF功能需要设置配置:appendonly yes,默认不开启。AOF文件名 | ||
+ | 通过appendfilename配置设置,默认文件名是appendonly.aof。保存路径同 | ||
+ | RDB持久化方式一致,通过dir配置指定。AOF的工作流程操作:命令写入 | ||
+ | (append)、文件同步(sync)、文件重写(rewrite)、重启加载 | ||
+ | (load),如图5-2所示 | ||
+ | |||
+ | ·配置为everysec,是建议的同步策略,也是默认配置,做到兼顾性能和 | ||
+ | 数据安全性。理论上只有在系统突然宕机的情况下丢失1秒的数据。(严格 | ||
+ | 来说最多丢失1秒数据是不准确的 | ||
+ | |||
+ | 还是建议在配置文件配置上 | ||
+ | |||
+ | # appendfsync always | ||
+ | appendfsync everysec | ||
+ | # appendfsync no | ||
+ | |||
+ | |||
+ | appendonly yes 打开aof 持久化 #默认是no | ||
+ | |||
+ | 5.2.4 重写机制 不全明 | ||
+ | |||
+ | |||
+ | 5.2.5 重启加载 | ||
+ | AOF持久化开启且存在AOF文件时,优先加载AOF文件, | ||
+ | AOF关闭或者AOF文件不存在时,加载RDB文件 | ||
+ | |||
+ | 5.3 问题定位与优化 | ||
+ | |||
+ | 5.3.1 | ||
+ | |||
+ | fork耗时问题定位:对于高流量的Redis实例OPS可达5万以上,如果fork | ||
+ | 操作耗时在秒级别将拖慢Redis几万条命令执行,对线上应用延迟影响非常 | ||
+ | 明显。正常情况下fork耗时应该是每GB消耗20毫秒左右。可以在info stats统 | ||
+ | 计中查latest_fork_usec指标获取最近一次fork操作耗时,单位微秒。 | ||
+ | n | ||
+ | 如何改善fork操作的耗时: | ||
+ | 1)优先使用物理机或者高效支持fork操作的虚拟化技术,避免使用 | ||
+ | Xen。 | ||
+ | |||
+ | 2)控制Redis实例最大可用内存,fork耗时跟内存量成正比,线上建议 | ||
+ | 每个Redis实例内存控制在10GB以内。 | ||
+ | |||
+ | 3)合理配置Linux内存分配策略,避免物理内存不足导致fork失败,具 | ||
+ | 体细节见12.1节“Linux配置优化”。 | ||
+ | |||
+ | 5.3.2 子进程开销监控和优化 | ||
+ | |||
+ | 5.3.3 AOF追加阻塞 | ||
+ | |||
+ | 5。4 | ||
+ | # Persistence from bsd | ||
+ | loading:0 | ||
+ | rdb_changes_since_last_save:0 | ||
+ | rdb_bgsave_in_progress:0 | ||
+ | rdb_last_save_time:1567955166 | ||
+ | rdb_last_bgsave_status:ok | ||
+ | rdb_last_bgsave_time_sec:-1 | ||
+ | rdb_current_bgsave_time_sec:-1 | ||
+ | aof_enabled:0 | ||
+ | aof_rewrite_in_progress:0 | ||
+ | aof_rewrite_scheduled:0 | ||
+ | aof_last_rewrite_time_sec:-1 | ||
+ | aof_current_rewrite_time_sec:-1 | ||
+ | aof_last_bgrewrite_status:ok | ||
+ | aof_last_write_status:ok | ||
+ | |||
+ | </pre> | ||
+ | |||
+ | [https://www.jianshu.com/p/0d626a8a1177 redis源码分析(五):数据持久化] | ||
+ | |||
+ | [https://www.v2ex.com/t/219551 redis 本身有持久化,为什么还要写进 mysql ] | ||
+ | |||
+ | |||
+ | [https://gsmtoday.github.io/2018/07/30/Redis%E6%8C%81%E4%B9%85%E5%8C%96%E6%80%BB%E7%BB%93/ Redis持久化总结 ] | ||
+ | |||
+ | https://blog.csdn.net/kfengqingyangk/article/details/53454309 | ||
+ | |||
+ | https://blog.csdn.net/ljl890705/article/details/51039015 | ||
+ | |||
+ | |||
+ | |||
+ | [https://www.jianshu.com/p/cbe1238f592a Redis持久化:RDB(快照)和AOF(写命令)] | ||
+ | |||
+ | =* chpater 6 Redis复制= | ||
+ | |||
+ | |||
+ | |||
+ | [https://blog.csdn.net/houjixin/article/details/27680183 Redis 数据同步机制分析] | ||
+ | =* chpater 7 Redis的噩梦:阻塞= | ||
+ | |||
+ | 2019年 9月 9日 星期一 14时5 | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==** 7.1 发现== | ||
+ | |||
+ | 应用方加入异常监控之后还存在一个问题,当开发人员接到异常报警 | ||
+ | 后,通常会去线上服务器查看错误日志细节。这时如果应用操作的是多个 | ||
+ | 404Redis节点(比如使用Redis集群),如何决定是哪一个节点超时还是所有的 | ||
+ | 节点都有超时呢?这是线上很常见的需求,但绝大多数的客户端类库并没有 | ||
+ | 在异常信息中打印ip和port信息,导致无法快速定位是哪个Redis节点超时。 | ||
+ | 不过修改Redis客户端成本很低,比如Jedis只需要修改Connection类下的 | ||
+ | connect、sendCommand、readProtocolWithCheckingBroken方法专门捕获连 | ||
+ | 接,发送命令,协议读取事件的异常。由于客户端类库都会保存ip和port信 | ||
+ | 息,当异常发生时很容易打印出对应节点的ip和port,辅助我们快速定位问 | ||
+ | 题节点。 | ||
+ | |||
+ | ==** 7.2 内在原因 == | ||
+ | |||
+ | .如何发现慢查询 | ||
+ | Redis原生提供慢查询统计功能,执行slowlog get{n}命令可以获取最近 | ||
+ | 的n条慢查询命令,默认对于执行超过10毫秒的命令都会记录到一个定长队 | ||
+ | 列中,线上实例建议设置为1毫秒便于及时发现毫秒级以上的命令 | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===7.2.2=== | ||
+ | CPU饱和 | ||
+ | |||
+ | 首先判断当前Redis的并 | ||
+ | 发量是否达到极限,建议使用统计命令redis-cli-h{ip}-p{port}--stat获取当前 | ||
+ | Redis使用情况,该命令每秒输出一行统计信息 | ||
+ | |||
+ | |||
+ | http://www.redis.io/topics/latency。 | ||
+ | |||
+ | |||
+ | ===7.3.1=== | ||
+ | CPU竞争 | ||
+ | 对于开启了持久化或参与复制的主节点不建议绑定CPU。 | ||
+ | |||
+ | =* 第8章 理解内存= | ||
+ | <pre> | ||
+ | 192.168.10.201:7000> info memory | ||
+ | # Memory | ||
+ | used_memory:2653536 | ||
+ | used_memory_human:2.53M | ||
+ | used_memory_rss:17285120 | ||
+ | used_memory_rss_human:16.48M | ||
+ | used_memory_peak:2756424 | ||
+ | used_memory_peak_human:2.63M | ||
+ | used_memory_peak_perc:96.27% | ||
+ | used_memory_overhead:2580244 | ||
+ | used_memory_startup:1464224 | ||
+ | used_memory_dataset:73292 | ||
+ | used_memory_dataset_perc:6.16% | ||
+ | allocator_allocated:3146048 | ||
+ | allocator_active:3551232 | ||
+ | allocator_resident:12943360 | ||
+ | total_system_memory:16808693760 | ||
+ | total_system_memory_human:15.65G | ||
+ | used_memory_lua:38912 | ||
+ | used_memory_lua_human:38.00K | ||
+ | used_memory_scripts:216 | ||
+ | used_memory_scripts_human:216B | ||
+ | number_of_cached_scripts:1 | ||
+ | maxmemory:0 | ||
+ | maxmemory_human:0B | ||
+ | maxmemory_policy:noeviction | ||
+ | allocator_frag_ratio:1.13 | ||
+ | allocator_frag_bytes:405184 | ||
+ | allocator_rss_ratio:3.64 | ||
+ | allocator_rss_bytes:9392128 | ||
+ | rss_overhead_ratio:1.34 | ||
+ | rss_overhead_bytes:4341760 | ||
+ | mem_fragmentation_ratio:6.62 | ||
+ | mem_fragmentation_bytes:14672608 | ||
+ | mem_not_counted_for_evict:612 | ||
+ | mem_replication_backlog:1048576 | ||
+ | mem_clients_slaves:16922 | ||
+ | mem_clients_normal:49694 | ||
+ | mem_aof_buffer:612 | ||
+ | mem_allocator:jemalloc-5.1.0 | ||
+ | active_defrag_running:0 | ||
+ | lazyfree_pending_objects:0 | ||
+ | |||
+ | |||
+ | 需要重点关注的指标有:used_memory_rss和used_memory以及它们的比 | ||
+ | mem_fragmentation_ratio。 | ||
+ | |||
+ | 详情 | ||
+ | |||
+ | # Memory | ||
+ | #由Redis分配器分配的内存总量,以字节(byte)为单位 | ||
+ | used_memory:2653536 | ||
+ | used_memory_human:2.53M | ||
+ | used_memory_rss:17285120 | ||
+ | |||
+ | mem_fragmentation_ratio:6.62</pre> | ||
+ | |||
+ | |||
+ | ===*** 8.1.2内存消耗划分=== | ||
+ | <pre> | ||
+ | |||
+ | 开发环境的数据 | ||
+ | # Memory | ||
+ | |||
+ | used_memory:2653536 #由Redis分配器分配的内存总量,以字节(byte)为单位 | ||
+ | used_memory_human:2.53M | ||
+ | used_memory_rss:17285120 | ||
+ | |||
+ | mem_fragmentation_ratio:6.62 | ||
+ | |||
+ | 基础 | ||
+ | 1 Byte = 8 Bits | ||
+ | |||
+ | 1 KB = 1024 Bytes | ||
+ | |||
+ | 1 MB = 1024 KB | ||
+ | |||
+ | 1 GB = 1024 MB | ||
+ | |||
+ | |||
+ | Redis进程内消耗主要包括:自身内存+对象内存+缓冲内存+内存碎片, | ||
+ | 中Redis空进程自身内存消耗非常少,通常used_memory_rss在3MB左右, | ||
+ | used_memory在800KB左右,一个空的Redis进程消耗内存可以忽略不计。 | ||
+ | is主要内存消耗如图8-1所示。下面介绍另外三种内存消耗。 | ||
+ | |||
+ | used_memory:2653536 =2.5306Mb | ||
+ | |||
+ | 1.对象内存 | ||
+ | |||
+ | 2.缓冲内存 | ||
+ | |||
+ | 3.内存碎片 | ||
+ | |||
+ | Redis默认的内存分配器采用jemalloc,可选的分配器还有:glibc、 | ||
+ | tcmalloc。内存分配器为了更好地管理和重复利用内存,分配内存策略一般 | ||
+ | 采用固定范围的内存块进行分配。例如jemalloc在64位系统中将内存空间划 | ||
+ | 分为:小、大、巨大三个范围。每个范围内又划分为多个小的内存块单位, | ||
+ | 如下所示: | ||
+ | |||
+ | |||
+ | </pre> | ||
+ | |||
+ | ===***8.1.3 子进程内存消耗=== | ||
+ | <pre> | ||
+ | |||
+ | 子进程内存消耗主要指执行AOF/RDB重写时Redis创建的子进程内存消 | ||
+ | 耗。Redis执行fork操作产生的子进程内存占用量对外表现为与父进程相同, | ||
+ | 理论上需要一倍的物理内存来完成重写操作。但Linux具有写时复制技术 | ||
+ | (copy-on-write),父子进程会共享相同的物理内存页,当父进程处理写请 | ||
+ | 求时会对需要修改的页复制出一份副本完成写操作,而子进程依然读取fork | ||
+ | 时整个父进程的内存快照。 | ||
+ | |||
+ | 当分别开启和关闭THP时,子进程内存 | ||
+ | 消耗有天壤之别。如果在高并发写的场景下开启THP,子进程内存消耗可能 | ||
+ | 是父进程的数倍,极易造成机器物理内存溢出,从而触发SWAP或OOM | ||
+ | killer,更多关于THP细节见12.1节“Linux配置优化”。 | ||
+ | </pre> | ||
+ | ====子进程内存消耗总结如下:==== | ||
+ | <pre> | ||
+ | ·Redis产生的子进程并不需要消耗1倍的父进程内存,实际消耗根据期 | ||
+ | 间写入命令量决定,但是依然要预留出一些内存防止溢出。 | ||
+ | |||
+ | ·需要设置sysctl vm.overcommit_memory=1允许内核可以分配所有的物理 | ||
+ | 内存,防止Redis进程执行fork时因系统剩余内存不足而失败。 | ||
+ | |||
+ | ·排查当前系统是否支持并开启THP,如果开启建议关闭,防止copy-on- | ||
+ | write期间内存过度消耗。 | ||
+ | |||
+ | </pre> | ||
+ | |||
+ | |||
+ | ==**8.2 内存管理== | ||
+ | ===8.2.1 设置内存上限=== | ||
+ | <pre> | ||
+ | |||
+ | Mem=`free -m | awk '/Mem:/{print $2}'` | ||
+ | redis_maxmemory=`expr $Mem / 8`000000 #here | ||
+ | [ -z "`grep ^maxmemory ${redis_install_dir}/etc/redis.conf`" ] && sed -i "s@maxmemory <byt | ||
+ | es>@maxmemory <bytes>\nmaxmemory `expr $Mem / 8`000000@" ${redis_install_dir}/etc/redis.conf | ||
+ | </pre> | ||
+ | |||
+ | ===8.2.2 动态调整内存上限=== | ||
+ | |||
+ | ===8.2.3 内存回收策略=== | ||
+ | 单机和主备的Redis实例默认的数据逐出策略为不逐出(noeviction ? | ||
+ | |||
+ | ==8.3 内存优化== | ||
+ | ===8.3.1 redisObject对象 === | ||
+ | 开发提示 | ||
+ | 高并发写入场景中,在条件允许的情况下,建议字符串长度控制在39字 | ||
+ | ,减少创建redisObject内存分配次数,从而提高性能。 | ||
+ | ===8.3.2 缩减键值对象 === | ||
+ | |||
+ | ===8.3.3 共享对象池 === | ||
+ | |||
+ | ===8.3.4字符串优化=== | ||
+ | |||
+ | === 8.3.5编码优化 === | ||
+ | |||
+ | =chapter 10 Cluster= | ||
+ | == == | ||
+ | |||
+ | == == | ||
+ | |||
+ | |||
+ | == == | ||
+ | |||
+ | == == | ||
+ | =redis学习(五) redis过期时间= | ||
+ | |||
+ | <pre> | ||
+ | 1.EXPIRE PEXPIRE | ||
+ | |||
+ | EXPIRE 接口定义:EXPIRE key "seconds" | ||
+ | 接口描述:设置一个key在当前时间"seconds"(秒)之后过期。返回1代表设置成功,返回0代表key不存在或者无法设置过期时间。 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | [https://www.cnblogs.com/xiaoxiongcanguan/p/9937433.html redis学习(五) redis过期时间] | ||
+ | |||
+ | [https://blog.csdn.net/weixin_38399962/article/details/82697498 Redis 更新(set) key值 会重置过期时间问题] | ||
+ | |||
+ | =redis info命令详解= | ||
+ | == memory : 内存信息,包含以下域== | ||
+ | <pre> | ||
+ | used_memory:35795152 #由Redis分配器分配的内存总量,以字节(byte)为单位 | ||
+ | used_memory_human:34.14M #以MB为单位返回由Redis分配器分配的内存总量 | ||
+ | used_memory_rss:50876416 #从操作系统的角度,返回 Redis 已分配的内存总量(俗称常驻集大小) | ||
+ | used_memory_peak:595513248 #Redis 的内存消耗峰值(以字节为单位) | ||
+ | used_memory_peak_human:567.93M #以MB为单位返回Redis 的内存消耗峰值 | ||
+ | used_memory_lua:35840 #Lua 引擎所使用的内存大小(以字节为单位) | ||
+ | mem_fragmentation_ratio:1.42 #used_memory_rss 和 used_memory 之间的比率 | ||
+ | mem_allocator:jemalloc-3.6.0 #在编译时指定的, Redis 所使用的内存分配器。可以是 libc 、 jemalloc 或者 tcmalloc 。 | ||
+ | </pre> | ||
+ | |||
+ | [https://blog.csdn.net/lang_man_xing/article/details/38539057 redis info命令详解] | ||
+ | |||
+ | [https://segmentfault.com/a/1190000004682946 redis info命令详细说明] | ||
+ | |||
+ | =redis.conf 详解= | ||
+ | <pre> | ||
+ | |||
+ | </pre> | ||
+ | https://www.cnblogs.com/kreo/p/4423362.html | ||
+ | |||
+ | https://blog.csdn.net/kfengqingyangk/article/details/53454309 | ||
+ | |||
+ | https://blog.csdn.net/ljl890705/article/details/51039015 | ||
+ | |||
+ | https://blog.csdn.net/qq_19707521/article/details/70676213 | ||
+ | |||
+ | https://www.jianshu.com/p/fa27ddf84455 | ||
+ | |||
+ | |||
+ | [https://www.cnblogs.com/uglyliu/p/8052648.html redis.conf 配置项说明如] | ||
+ | |||
+ | =[[Docker redis]]= | ||
=see also= | =see also= | ||
− | |||
− | [[category: | + | [[Redis备份与恢复]] |
+ | |||
+ | [[Redis安全]] | ||
+ | |||
+ | https://stackoverflow.com/questions/49061445/when-redis-get-key-in-slave-why-redirect-to-master | ||
+ | |||
+ | [https://www.cnblogs.com/zhangweizhong/p/7531471.html 运维常用命令] | ||
+ | |||
+ | [https://blog.csdn.net/liqingtx/article/details/60330555 超强、超详细Redis入门教程] | ||
+ | |||
+ | [https://www.runoob.com/redis/redis-php.html PHP 使用 Redis] | ||
+ | |||
+ | [https://www.cnblogs.com/themost/p/8464490.html redis常用命令] | ||
+ | |||
+ | |||
+ | [https://www.runoob.com/redis/redis-server.html Redis 服务器runoob] | ||
+ | |||
+ | [https://www.w3cschool.cn/redis_all_about/ Redis开发运维实践指南] | ||
+ | |||
+ | [http://redisdoc.com/string/setex.html SETEX key seconds value] | ||
+ | |||
+ | [https://www.jianshu.com/p/2639549bedc8 使用python来操作redis用法详解] | ||
+ | |||
+ | [https://zhuanlan.zhihu.com/p/47692277 Redis 常用操作命令,非常详细!] | ||
+ | |||
+ | |||
+ | |||
+ | [[category:redis]] [[category:ops]] |
2020年6月24日 (三) 10:49的版本
目录
清理
redis-cli -h 192.168.10.213 -c -p 7004 -a passwD9923 KEYS "dict_telegram_group_telegram_group_share_id" | xargs -I {} redis-cli -h 192.168.10.213 -c -p 7004 -a passwD9923 del {}
usage
redis基本命令 String
非交互 redis-cli -h -p youcommand redis-cli -h 127.0.0.1 127.0.0.1:6379> Auth upassword set hey you set love you redis> SET key1 "Hello" "OK" redis> SET key2 "World" "OK" redis> DEL key1 key2 key3 (integer) 2 keys *
SETEX 命令的效果和以下两个命令的效果类似: SET key value EXPIRE key seconds # 设置生存时间 SETEX 和这两个命令的不同之处在于 SETEX 是一个原子(atomic)操作, 它可以在同一时间内完成设置值和设置过期时间这两个操作, 因此 SETEX 命令在储存缓存的时候非常实用。
usage from 运维开发与运维
创建新列表 127.0.0.1:6379> rpush listkey c java b a (integer) 4 #查看列表 -1 就是所有 了 127.0.0.1:6379> lrange listkey 0 -1 1) "c" 2) "java" 3) "b" 4) "a" 2.4.1 1 添加操作 #在 b前插入java 127.0.0.1:6379> linsert listkey before b java (integer) 0 127.0.0.1:6379> lrange listkey 0 -1 2.查找 2 到 4 127.0.0.1:6379> lrange listkey 1 3 1) "java" 2) "b" 3) "a" 127.0.0.1:6379> lrange listkey 1 3 1) "java" 2) "b" 3) "a" 3.删除 lpop key (1) 左弹出 127.0.0.1:6379> lpop listkey "c" 右弹出 rpop key (3)删除指定元素 127.0.0.1:6379> lrem listkey 4 a #删除左开始的4个为a的元素 (integer) 1 (4) 127.0.0.1:6379> lrange listkey 0 -1 1) "c" 2) "java" 3) "b" 127.0.0.1:6379> ltrim listkey 1 3 #1 到3 被删除了 OK 127.0.0.1:6379> lrange listkey 0 -1 1) "java" 2) "b" 4.修改 #把第三个改为python 127.0.0.1:6379> rpush listkey c java b a (integer) 4 127.0.0.1:6379> lset listkey 2 python OK 5 阻塞操作 blpop brpop 2.4.2 内部编码
2.5 集合
2.5.1 命令 (1) add 27.0.0.1:6379> exists myset (integer) 0 127.0.0.1:6379> sadd myset a b c (integer) 3 127.0.0.1:6379> sadd myset a b (integer) 0 (2) del 127.0.0.1:6379> srem myset a b (integer) 2 (3) count 127.0.0.1:6379> scard myset (integer) 1 (4) exists 127.0.0.1:6379> sismember myset c (integer) 1 (5)随机 127.0.0.1:6379> sadd myset a b c (integer) 2 127.0.0.1:6379> srandmember myset 2 1) "a" 2) "b" (6) 127.0.0.1:6379> spop myset "a" 127.0.0.1:6379> srandmember myset 2 1) "c" 2) "b" 7)取得所有 127.0.0.1:6379> smembers myset 1) "c" 2) "b" 2.集合间操作 2.集合间操作 127.0.0.1:6379> SADD user:1:follow it music his sports (integer) 4 127.0.0.1:6379> SADD user:2:follow it music his sports (integer) 4 交集 127.0.0.1:6379> sinter user:1:follow user:2:follow 1) "sports" 2) "it" 并集 127.0.0.1:6379> sunion user:1:follow user:2:follow 1) "sports" 2) "his" 3) "music" (4) 结果保存 4) "it" 127.0.0.1:6379> sdiff user:1:follow user:2:follow 2.5.2 内部编码 127.0.0.1:6379> sadd setkey 1 2 3 4 (integer) 4 127.0.0.1:6379> object encoding setkey "intset" 2.5.3 使用场景
2.6 有序集合
2.6.1 # 127.0.0.1:6379> zadd user:ranking 251 tom (integer) 1 27.0.0.1:6379> zadd user:ranking 1 kris 91 mike 220 frank 220 tim 250 martin (integer) 5 127.0.0.1:6379> zcard user:ranking (integer) 6 127.0.0.1:6379> zscore user:ranking tom "251" 排名 127.0.0.1:6379> zrank user:ranking tom (integer) 5 127.0.0.1:6379> zrevrank user:ranking tom (integer) 0 删除成员 127.0.0.1:6379> zrem user:ranking mike (integer) 1 加了9分 127.0.0.1:6379> zincrby user:ranking 9 tom "260" (7)返回指定排名范围的成员 127.0.0.1:6379> zrange user:ranking 0 2 withscores 1) "kris" 2) "1" 3) "mike" 4) "91" 5) "frank" 6) "200" 127.0.0.1:6379> zrevrange user:ranking 0 2 withscores 1) "tom" 2) "251" 3) "martin" 4) "250" 5) "tim" 6) "220" 8)返回指定分数范围的成员 127.0.0.1:6379> zrangebyscore user:ranking (200 +inf withscores 1) "tim" 2) "220" 3) "martin" 4) "250" 5) "tom" 6) "251" (9)返回指定分数范围成员个数 返回200到221分的成员的个数 127.0.0.1:6379> zcount user:ranking 200 221 (integer) 2 10)删除指定排名内的升序元素 2.6.1 2019年 8月23日 星期五 14时41分48秒 CST 2.集合间的操作 两个有序集合导入到Redis中 zadd user:ranking:1 1 kris 91 mike 200 frank 220 tim 250 martin zadd user:ranking:2 8 james 77 mike 625 martin 888 tom Redis DEL 命令 > DEL KEY_NAME
Redis DEL 命令 - 该命令用于在 key 存在是删除 key
2.7 键管理
2.7.1 单个键管理
2019年 8月31日 星期六 16时03分38秒 CST 1.key rename rename key newkey renamenx 比较安全 127.0.0.1:6379> get evan "36" 127.0.0.1:6379> rename evan eva OK 127.0.0.1:6379> get eva "36" 127.0.0.1:6379> get evan (nil) 2.随机返回 randomkey 3.key 过期 2019年 9月 1日 127.0.0.1:6379> set hello world OK 127.0.0.1:6379> expire hello 10 (integer) 1 127.0.0.1:6379> ttl hello (integer) 1 127.0.0.1:6379> ttl hello (integer) -2 4.key 迁移 (1) move 不用 知道就行了 (2)dump + restore (3)migrate
2.7.2 遍历键
key partern get key * 2.渐进式子 scan
2.7.3 数据库管理
1.切换 select 默认是 0 127.0.0.1:6379[2]> set hello love OK 127.0.0.1:6379[2]> SELECT 3 OK 127.0.0.1:6379[3]> get hello (nil) 2.flushdb flushall flushall 全部数据不见了
Chpater 3
慢查询分析
redis shell
redis-cli -r evan@latop:~$ redis-cli -r 3 ping PONG PONG PONG evan@latop:~$ redis-cli -r 3 -i 1 ping PONG PONG PONG evan@latop:~$ echo "world" |redis-cli -x set hello 127.0.0.1:6379> get hello "world\n" -c cluster -a (auth) 6.--scan and --pattern 7 --slave 8 --rdb 12 -- latency 13 --stat 实时 比info 简单些 redis-cli --stat ------- data ------ --------------------- load -------------------- - child - keys mem clients blocked requests connections 1 838.51K 1 0 5 (+0) 2 1 838.51K 1 0 6 (+1) 2 1 838.51K 1 0 7 (+1) 2 14 --no-raw 原始格式 --raw 格式化过 127.0.0.1:6379> set evan "你�好" OK 127.0.0.1:6379> get evan "\xe4\xbd\xa0\xe5\x8f\xe5\xa5\xbd" redis-cli --raw get evan 你�好 3.2.2 redis-server --test-memory 1024
Chpater 5 持久化
redis的存储功能只是用做备份,恢复的功能,全量数据还是存储在内存中。 redis内部提供了两种固化数据的方式,aof 和rdb。 运维提示 当硬盘坏或者 写满时 可以 config set dir {newDir} 在线修改文件路径 到可用的磁盘 再执行bgsave 同样可以用于aof 5.2 AOF 5.2.1 使用AOF 开启AOF功能需要设置配置:appendonly yes,默认不开启。AOF文件名 通过appendfilename配置设置,默认文件名是appendonly.aof。保存路径同 RDB持久化方式一致,通过dir配置指定。AOF的工作流程操作:命令写入 (append)、文件同步(sync)、文件重写(rewrite)、重启加载 (load),如图5-2所示 ·配置为everysec,是建议的同步策略,也是默认配置,做到兼顾性能和 数据安全性。理论上只有在系统突然宕机的情况下丢失1秒的数据。(严格 来说最多丢失1秒数据是不准确的 还是建议在配置文件配置上 # appendfsync always appendfsync everysec # appendfsync no appendonly yes 打开aof 持久化 #默认是no 5.2.4 重写机制 不全明 5.2.5 重启加载 AOF持久化开启且存在AOF文件时,优先加载AOF文件, AOF关闭或者AOF文件不存在时,加载RDB文件 5.3 问题定位与优化 5.3.1 fork耗时问题定位:对于高流量的Redis实例OPS可达5万以上,如果fork 操作耗时在秒级别将拖慢Redis几万条命令执行,对线上应用延迟影响非常 明显。正常情况下fork耗时应该是每GB消耗20毫秒左右。可以在info stats统 计中查latest_fork_usec指标获取最近一次fork操作耗时,单位微秒。 n 如何改善fork操作的耗时: 1)优先使用物理机或者高效支持fork操作的虚拟化技术,避免使用 Xen。 2)控制Redis实例最大可用内存,fork耗时跟内存量成正比,线上建议 每个Redis实例内存控制在10GB以内。 3)合理配置Linux内存分配策略,避免物理内存不足导致fork失败,具 体细节见12.1节“Linux配置优化”。 5.3.2 子进程开销监控和优化 5.3.3 AOF追加阻塞 5。4 # Persistence from bsd loading:0 rdb_changes_since_last_save:0 rdb_bgsave_in_progress:0 rdb_last_save_time:1567955166 rdb_last_bgsave_status:ok rdb_last_bgsave_time_sec:-1 rdb_current_bgsave_time_sec:-1 aof_enabled:0 aof_rewrite_in_progress:0 aof_rewrite_scheduled:0 aof_last_rewrite_time_sec:-1 aof_current_rewrite_time_sec:-1 aof_last_bgrewrite_status:ok aof_last_write_status:ok
https://blog.csdn.net/kfengqingyangk/article/details/53454309
https://blog.csdn.net/ljl890705/article/details/51039015
* chpater 6 Redis复制
* chpater 7 Redis的噩梦:阻塞
2019年 9月 9日 星期一 14时5
** 7.1 发现
应用方加入异常监控之后还存在一个问题,当开发人员接到异常报警 后,通常会去线上服务器查看错误日志细节。这时如果应用操作的是多个 404Redis节点(比如使用Redis集群),如何决定是哪一个节点超时还是所有的 节点都有超时呢?这是线上很常见的需求,但绝大多数的客户端类库并没有 在异常信息中打印ip和port信息,导致无法快速定位是哪个Redis节点超时。 不过修改Redis客户端成本很低,比如Jedis只需要修改Connection类下的 connect、sendCommand、readProtocolWithCheckingBroken方法专门捕获连 接,发送命令,协议读取事件的异常。由于客户端类库都会保存ip和port信 息,当异常发生时很容易打印出对应节点的ip和port,辅助我们快速定位问 题节点。
** 7.2 内在原因
.如何发现慢查询 Redis原生提供慢查询统计功能,执行slowlog get{n}命令可以获取最近 的n条慢查询命令,默认对于执行超过10毫秒的命令都会记录到一个定长队 列中,线上实例建议设置为1毫秒便于及时发现毫秒级以上的命令
7.2.2
CPU饱和
首先判断当前Redis的并 发量是否达到极限,建议使用统计命令redis-cli-h{ip}-p{port}--stat获取当前 Redis使用情况,该命令每秒输出一行统计信息
http://www.redis.io/topics/latency。
7.3.1
CPU竞争 对于开启了持久化或参与复制的主节点不建议绑定CPU。
* 第8章 理解内存
192.168.10.201:7000> info memory # Memory used_memory:2653536 used_memory_human:2.53M used_memory_rss:17285120 used_memory_rss_human:16.48M used_memory_peak:2756424 used_memory_peak_human:2.63M used_memory_peak_perc:96.27% used_memory_overhead:2580244 used_memory_startup:1464224 used_memory_dataset:73292 used_memory_dataset_perc:6.16% allocator_allocated:3146048 allocator_active:3551232 allocator_resident:12943360 total_system_memory:16808693760 total_system_memory_human:15.65G used_memory_lua:38912 used_memory_lua_human:38.00K used_memory_scripts:216 used_memory_scripts_human:216B number_of_cached_scripts:1 maxmemory:0 maxmemory_human:0B maxmemory_policy:noeviction allocator_frag_ratio:1.13 allocator_frag_bytes:405184 allocator_rss_ratio:3.64 allocator_rss_bytes:9392128 rss_overhead_ratio:1.34 rss_overhead_bytes:4341760 mem_fragmentation_ratio:6.62 mem_fragmentation_bytes:14672608 mem_not_counted_for_evict:612 mem_replication_backlog:1048576 mem_clients_slaves:16922 mem_clients_normal:49694 mem_aof_buffer:612 mem_allocator:jemalloc-5.1.0 active_defrag_running:0 lazyfree_pending_objects:0 需要重点关注的指标有:used_memory_rss和used_memory以及它们的比 mem_fragmentation_ratio。 详情 # Memory #由Redis分配器分配的内存总量,以字节(byte)为单位 used_memory:2653536 used_memory_human:2.53M used_memory_rss:17285120 mem_fragmentation_ratio:6.62
*** 8.1.2内存消耗划分
开发环境的数据 # Memory used_memory:2653536 #由Redis分配器分配的内存总量,以字节(byte)为单位 used_memory_human:2.53M used_memory_rss:17285120 mem_fragmentation_ratio:6.62 基础 1 Byte = 8 Bits 1 KB = 1024 Bytes 1 MB = 1024 KB 1 GB = 1024 MB Redis进程内消耗主要包括:自身内存+对象内存+缓冲内存+内存碎片, 中Redis空进程自身内存消耗非常少,通常used_memory_rss在3MB左右, used_memory在800KB左右,一个空的Redis进程消耗内存可以忽略不计。 is主要内存消耗如图8-1所示。下面介绍另外三种内存消耗。 used_memory:2653536 =2.5306Mb 1.对象内存 2.缓冲内存 3.内存碎片 Redis默认的内存分配器采用jemalloc,可选的分配器还有:glibc、 tcmalloc。内存分配器为了更好地管理和重复利用内存,分配内存策略一般 采用固定范围的内存块进行分配。例如jemalloc在64位系统中将内存空间划 分为:小、大、巨大三个范围。每个范围内又划分为多个小的内存块单位, 如下所示:
***8.1.3 子进程内存消耗
子进程内存消耗主要指执行AOF/RDB重写时Redis创建的子进程内存消 耗。Redis执行fork操作产生的子进程内存占用量对外表现为与父进程相同, 理论上需要一倍的物理内存来完成重写操作。但Linux具有写时复制技术 (copy-on-write),父子进程会共享相同的物理内存页,当父进程处理写请 求时会对需要修改的页复制出一份副本完成写操作,而子进程依然读取fork 时整个父进程的内存快照。 当分别开启和关闭THP时,子进程内存 消耗有天壤之别。如果在高并发写的场景下开启THP,子进程内存消耗可能 是父进程的数倍,极易造成机器物理内存溢出,从而触发SWAP或OOM killer,更多关于THP细节见12.1节“Linux配置优化”。
子进程内存消耗总结如下:
·Redis产生的子进程并不需要消耗1倍的父进程内存,实际消耗根据期 间写入命令量决定,但是依然要预留出一些内存防止溢出。 ·需要设置sysctl vm.overcommit_memory=1允许内核可以分配所有的物理 内存,防止Redis进程执行fork时因系统剩余内存不足而失败。 ·排查当前系统是否支持并开启THP,如果开启建议关闭,防止copy-on- write期间内存过度消耗。
**8.2 内存管理
8.2.1 设置内存上限
Mem=`free -m | awk '/Mem:/{print $2}'` redis_maxmemory=`expr $Mem / 8`000000 #here [ -z "`grep ^maxmemory ${redis_install_dir}/etc/redis.conf`" ] && sed -i "s@maxmemory <byt es>@maxmemory <bytes>\nmaxmemory `expr $Mem / 8`000000@" ${redis_install_dir}/etc/redis.conf
8.2.2 动态调整内存上限
8.2.3 内存回收策略
单机和主备的Redis实例默认的数据逐出策略为不逐出(noeviction ?
8.3 内存优化
8.3.1 redisObject对象
开发提示 高并发写入场景中,在条件允许的情况下,建议字符串长度控制在39字 ,减少创建redisObject内存分配次数,从而提高性能。
8.3.2 缩减键值对象
8.3.3 共享对象池
8.3.4字符串优化
8.3.5编码优化
chapter 10 Cluster
redis学习(五) redis过期时间
1.EXPIRE PEXPIRE EXPIRE 接口定义:EXPIRE key "seconds" 接口描述:设置一个key在当前时间"seconds"(秒)之后过期。返回1代表设置成功,返回0代表key不存在或者无法设置过期时间。
redis info命令详解
memory : 内存信息,包含以下域
used_memory:35795152 #由Redis分配器分配的内存总量,以字节(byte)为单位 used_memory_human:34.14M #以MB为单位返回由Redis分配器分配的内存总量 used_memory_rss:50876416 #从操作系统的角度,返回 Redis 已分配的内存总量(俗称常驻集大小) used_memory_peak:595513248 #Redis 的内存消耗峰值(以字节为单位) used_memory_peak_human:567.93M #以MB为单位返回Redis 的内存消耗峰值 used_memory_lua:35840 #Lua 引擎所使用的内存大小(以字节为单位) mem_fragmentation_ratio:1.42 #used_memory_rss 和 used_memory 之间的比率 mem_allocator:jemalloc-3.6.0 #在编译时指定的, Redis 所使用的内存分配器。可以是 libc 、 jemalloc 或者 tcmalloc 。
redis.conf 详解
https://www.cnblogs.com/kreo/p/4423362.html
https://blog.csdn.net/kfengqingyangk/article/details/53454309
https://blog.csdn.net/ljl890705/article/details/51039015
https://blog.csdn.net/qq_19707521/article/details/70676213
https://www.jianshu.com/p/fa27ddf84455
Docker redis
see also
https://stackoverflow.com/questions/49061445/when-redis-get-key-in-slave-why-redirect-to-master