info命令输出的数据可以分为10个分类,分别是:
server,clients,memory,persistence,stats,replication,cpu,commandstats,cluster,keyspace
为了快速定位并解决性能问题,我们选取其中几个作为参考:
redis:6379> info memory "# Memory used_memory:31590440 used_memory_human:30.13M used_memory_rss:38260736 used_memory_rss_human:36.49M used_memory_peak:31625024 used_memory_peak_human:30.16M used_memory_peak_perc:99.89% used_memory_overhead:9672728 used_memory_startup:862392 used_memory_dataset:21917712 used_memory_dataset_perc:71.33% allocator_allocated:31686224 allocator_active:32690176 allocator_resident:35946496 total_system_memory:16585785344 total_system_memory_human:15.45G used_memory_lua:37888 used_memory_vm_eval:37888 used_memory_lua_human:37.00K used_memory_scripts_eval:0 number_of_cached_scripts:0 number_of_functions:0 number_of_libraries:0 used_memory_vm_functions:37888 used_memory_vm_total:75776 used_memory_vm_total_human:74.00K used_memory_functions:184 used_memory_scripts:184 used_memory_scripts_human:184B maxmemory:4294967296 maxmemory_human:4.00G maxmemory_policy:allkeys-lru allocator_frag_ratio:1.03 allocator_frag_bytes:1003952 allocator_rss_ratio:1.10 allocator_rss_bytes:3256320 rss_overhead_ratio:1.06 rss_overhead_bytes:2314240 mem_fragmentation_ratio:1.21 mem_fragmentation_bytes:6650024 mem_not_counted_for_evict:0 mem_replication_backlog:0 mem_total_replication_buffers:0 mem_clients_slaves:0 mem_clients_normal:24072 mem_cluster_links:0 mem_aof_buffer:0 mem_allocator:jemalloc-5.2.1 active_defrag_running:0 lazyfree_pending_objects:0 lazyfreed_objects:0 "
used_memory是Redis使用的内存总量,包含了实际缓存占用的内存和Redis自身运行所占用的内存。used_memory_rss:从操作系统上显示已经分配的内存总量。maxmemory最大内存容量。
如果Redis使用的内存超过了最大可用内存,那么操作系统开始进行内存与swap空间交换,这时Redis和依赖Redis上数据的应用会受到严重的性能影响,所以通过查看used_memory指标可知道Redis的性能情况;
运行过程中触发RDB功能时,Redis会fork一个子进程把当前内存中的数据完全复制一份写入到硬盘上,若当前使用内存超过可用内存的45%,就会触发内存交换,大量频繁的更新操作,可能会加剧性能下降。
redis:6379> info stats "# Stats total_connections_received:395 total_commands_processed:530848 instantaneous_ops_per_sec:3 total_net_input_bytes:41630627 total_net_output_bytes:12904524 instantaneous_input_kbps:0.22 instantaneous_output_kbps:0.02 rejected_connections:0 total_reads_processed:531868 total_writes_processed:531477 io_threaded_reads_processed:0 io_threaded_writes_processed:0 reply_buffer_shrinks:1729 reply_buffer_expands:1356 "
Redis是单线程模型,客户端发送过来的命令会按照顺序执行,通过total_connections_received获取命令数量,如果命令处理总数处于上升或下降状态,那么可能是有2个原因引起的:
解决办法有:
Redis的延迟数据是无法从info信息中获取的,可以用 Redis-cli工具加 --latency参数运行。
redis-cli -h 127.0.0.1 -p 6379 --latency
该命令会统计三个延迟指标:最小值(min),最大值(max)和平均值(avg),单位是ms。如果发现延迟较大,有一些方法可以定位延迟出现的情况:
redis:6379> info clients "# Clients connected_clients:2 cluster_connections:0 maxclients:10000 client_recent_max_input_buffer:20480 client_recent_max_output_buffer:0 blocked_clients:0 tracking_clients:0 clients_in_timeout_table:0 "
Redis默认允许客户端连接的最大数量是10000,但是连接数过大会对性能影响较大;自Redis2.6以后,允许在配置文件(Redis.conf)maxclients属性上修改客户端连接的最大数,也可以通过在Redis-cli工具上输入config set maxclients 去设置最大连接数。
在info中通过mem_fragmentation_ratio = used_memory_rss/used_memory,
如果内存碎片率超过1.5,那可能是操作系统或Redis实例中内存管理变差的表现。解决方法:
缓存穿透是指查询缓存中一个不存在的数据,请求直接访问到数据库服务。大量的恶意请求会导致存储层压力过大而崩溃。解决方案:
大批量的key同时失效,导致大量请求同时打向数据库,造成数据库压力过大,甚至直接挂掉。解决方案是失效时间随机化,可以是一个固定时间+随机时间方式来生成,更加保险的方案可以加分布式锁,拿到锁的才去访问数据库。
缓存雪崩是指缓存层挂掉之后,所有请求都打向数据库,数据库扛不住挂掉,导致对应的服务也挂掉,从而影响整个链路服务雪崩挂掉。解决方案:
引入缓存后,并发请求可能导致缓存中的数据就会与db数据不一致。如果先更新缓存,然后更新DB失败,那么下一个请求过来读取的缓存数据不是最新的。如果先更新db再更新缓存,更新DB时的请求读取数据是缓存的旧值。
保障缓存一致性可采用方案:加锁——淘汰缓存——更新DB——重新刷进缓存
Redis中一个字符串最大512MB,一个二级数据结构(如hash、list、set、zset)可以存储大约40亿个(2^32-1)个元素,但实际中如果满足下面两种情况,就认为它是bigkey。
bigkey的坏处:
一般来说,string类型控制在10KB以内,hash、list、set、zset元素个数不要超过5000(超过5000了可以采用分拆思想)
在高并发环境下你需要一个高backlog值来避免慢客户端连接问题。注意Linux内核默默地将这个值减小到/proc/sys/net/core/somaxconn
的值,所以需要确认增大somaxconn和tcp_max_syn_backlog两个值来达到想要的效果。
redis在备份数据的时候,会fork出一个子进程,理论上child进程所占用的内存和parent是一样的,比如parent占用的内存为8G,这个时候也要同样分配8G的内存给child,如果内存无法负担,往往会造成redis服务器的down机或者IO负载过高,效率下降。所以内存分配策略应该设置为 1(表示内核允许分配所有的物理内存,而不管当前的内存状态如何)。
内存分配策略有三种
可选值:0、1、2。
0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
1, 不管需要多少内存,都允许申请。
2, 只允许分配物理内存和交换内存的大小(交换内存一般是物理内存的一半)。
Linux kernel 在2.6.38内核增加了 THP 特性,支持大内存页(2MB)分配,默认开启。当开启时可以降低 fork 子进程的速度,但 fork 操作之后,每个内存页从原来 4KB 变为 2MB,会大幅增加重写期间父进程内存消耗。同时每次写命令引起的复制内存页单位放大了512倍,会拖慢写操作的执行时间,导致大量写操作慢查询。
参考连接:https://blog.csdn.net/qq_39399966/article/details/101211939
关于redis性能问题分析和优化 - 踏雪无痕SS - 博客园