实战:Redis性能测试、调优和使用规范

13 篇文章 0 订阅
8 篇文章 0 订阅

概叙

Redis作为一种高性能的内存数据库,广泛应用于各种业务场景。然而,随着业务规模的扩大和数据量的增长,Redis的性能问题逐渐凸显出来。为了提高Redis的性能,本文将深入探讨Redis性能测试和优化方案,包括参数配置、数据结构、多线程、集群分片等方面,以及Redis使用规范。本文介绍了Redis性能压测、监控工具及优化方案。通过对Redis进行性能压测和监控,我们可以了解Redis的性能瓶颈和异常情况。通过对Redis进行优化,我们 可以提高Redis的性能和可用性,以满足实际应用的需求。

一、Redis性能测试

常用的Redis性能压测工具有:

Redis-benchmark是目前进行redis性能测试的主流工具,并且redis-benchmark是redis自带的工具,安装redis之后不需要安装即可直接使用。

1、redis-benchmark

redis-benchmark是 Redis自带的性能测试工具,可以通过命令行进行测试。以下是使用 redis-benchmark进行测试的命令:

redis-benchmark -h host -p port -c connections -n requests

其中,host为Redis服务器地址,port为Redis服务器端口号,connections为并发连接数,requests为请求数量。

2、JMeter

JMeter是一款 Java编写的性能测试工具,可以对Redis进行性能测试。

以下是使用JMeter进行测试的步骤:

  • 下载JMeter并安装
  • 安装Redis插件
  • 创建测试计划
  • 配置Redis连接信息
  • 添加测试元件
  • 运行测试计划

3、Memtier

Memtier是一款专门用于测试Redis和Memcached的性能测试工具, 可以模拟真实的应用场景进行测试。以下是使用Memtier进行测试的命令:

memtier_benchmark -s host -p port -c connections -n requests

其中,host为Redis服务器地址,port为Redis服务器端口号,connections为并发连接数,requests为请求数量。

常用的Redis监控工具有:

Redis监控工具可以帮助我们监控Redis的运行状态和性能指标,以及发现Redis的异常情况。

1、Redis Monitor

Redis Monitor是 Redis自带的监控工具,可以通过命令行进行监控。以下是使用 Redis Monitor进行监控的命令:

redis-cli monitor

2、Redis Desktop Manager

Redis Desktop Manager是一款 图形化的Redis管理工具,可以通过界面进行监控。它可以显示Redis服务器的状态、命令和响应时间等信息。

3、Redis Live

Redis Live是一款 开源的Redis监控工具,可以通过Web界面进行监控。它可以显示Redis服务器的实时状态、命令和响应时间等信息。

Benchmark性能测试

benchmark命令解读

  • 为了解 Redis 在不同配置环境下的性能表现,Redis 提供了一种行性能测试工具 redis-benchmark(也称压力测试工具),它通过同时执行多组命令实现对 Redis 的性能测试。
  • 性能测试的作用是让我们了解 Redis 服务器的性能优劣。在实际的业务场景中,性能测试是必不可少的。在业务系统上线之前,我们都需要清楚地了解 Redis 服务器的性能,从而避免发生某些意外情况,比如数据量过大会导致服务器宕机等。
  • 执行测试命令,要在 Redis 的安装目录下执行,命令如下所示:redis-benchmark [option] [option value]
  • 其中 option 为可选参数, option value 为具体的参数值。 redis-benchmark 命令的可选参数如下所示:

同时执行了 10000 个命令来检测 Redis 服务器的性能,示例如下:

执行指定的测试命令 :带参数的命令,使用示例如下

CNCLUKZK@LAPTOP-HGE63E13 MINGW64 /e/software/Redis
$ redis-benchmark.exe -h 127.0.0.1 -p 6379 -n 10000 -t set,get,rpush -q
SET: 50000.00 requests per second
GET: 50251.26 requests per second
RPUSH: 37878.79 requests per second

如何进行性能分析,使用100个并发,总共请求100000次

[root@VM-0-3-centos ~]# redis-benchmark -a 1322330916 -c 100 -n 100000
...
====== SET ======                                         #10w个请求进行set写入测试          
  100000 requests completed in 1.71 seconds
  #100个并发客户端
  100 parallel clients
  #每次写入3个字节
  3 bytes payload
  #只有一台服务器处理这些请求,测试单机性能
  keep alive: 1
  host configuration "save": 3600 1 300 100 60 10000
  host configuration "appendonly": yes
  multi-thread: no

#延迟百分比,一个请求处理过程及使用时间
Latency by percentile distribution:
0.000% <= 0.303 milliseconds (cumulative count 1)
50.000% <= 0.999 milliseconds (cumulative count 50380)
75.000% <= 1.303 milliseconds (cumulative count 75409)
87.500% <= 1.591 milliseconds (cumulative count 87663)
93.750% <= 1.903 milliseconds (cumulative count 93811)
96.875% <= 2.167 milliseconds (cumulative count 96962)
98.438% <= 2.423 milliseconds (cumulative count 98458)
99.219% <= 2.799 milliseconds (cumulative count 99223)
99.609% <= 3.199 milliseconds (cumulative count 99611)
99.805% <= 3.775 milliseconds (cumulative count 99806)
99.902% <= 5.007 milliseconds (cumulative count 99903)
99.951% <= 5.511 milliseconds (cumulative count 99952)
99.976% <= 5.743 milliseconds (cumulative count 99976)
99.988% <= 5.863 milliseconds (cumulative count 99988)
99.994% <= 5.919 milliseconds (cumulative count 99994)
99.997% <= 5.951 milliseconds (cumulative count 99997)
99.998% <= 5.975 milliseconds (cumulative count 99999)
99.999% <= 5.991 milliseconds (cumulative count 100000)
100.000% <= 5.991 milliseconds (cumulative count 100000)

#延迟的累积分布
Cumulative distribution of latencies:
0.000% <= 0.103 milliseconds (cumulative count 0)
0.001% <= 0.303 milliseconds (cumulative count 1)
0.029% <= 0.407 milliseconds (cumulative count 29)
0.083% <= 0.503 milliseconds (cumulative count 83)
1.643% <= 0.607 milliseconds (cumulative count 1643)
4.499% <= 0.703 milliseconds (cumulative count 4499)
10.197% <= 0.807 milliseconds (cumulative count 10197)
33.636% <= 0.903 milliseconds (cumulative count 33636)
51.101% <= 1.007 milliseconds (cumulative count 51101)
59.800% <= 1.103 milliseconds (cumulative count 59800)
68.475% <= 1.207 milliseconds (cumulative count 68475)
75.409% <= 1.303 milliseconds (cumulative count 75409)
80.703% <= 1.407 milliseconds (cumulative count 80703)
84.595% <= 1.503 milliseconds (cumulative count 84595)
88.159% <= 1.607 milliseconds (cumulative count 88159)
90.666% <= 1.703 milliseconds (cumulative count 90666)
92.561% <= 1.807 milliseconds (cumulative count 92561)
93.811% <= 1.903 milliseconds (cumulative count 93811)
95.103% <= 2.007 milliseconds (cumulative count 95103)
96.259% <= 2.103 milliseconds (cumulative count 96259)
99.562% <= 3.103 milliseconds (cumulative count 99562)
99.855% <= 4.103 milliseconds (cumulative count 99855)
99.913% <= 5.103 milliseconds (cumulative count 99913)
100.000% <= 6.103 milliseconds (cumulative count 100000)

#总结
Summary:
 #吞吐量总结:每秒58513.75个请求
  throughput summary: 58513.75 requests per second
  latency summary (msec):
          avg       min       p50       p95       p99       max
        1.146     0.296     0.999     2.007     2.663     5.991

...

Redis benchmark测试脚本自动化

测试需求:
        测试对象围绕Redis数据缓存功能,验证是否通过特定服务的情况下访问Redis服务的性能,本次性能测试考虑测性能指标包括QPS和延时;Redis测试范围包括:Redis操作单一key、操作多key及pipeline操作;测试场景覆盖通过特定服务及不通过特定服务两种情况下访问Redis。

测试步骤:
1、测试Redis 单一key,设置-r参数为1
测试命令:redis-benchmark -h redis-XXX.com -r 1 -c 100 –n 150000 -t get,set
2、测试Redis 多key,设置-r参数为50
测试命令:redis-benchmark -h redis-XXX.com -r 50 -c 100 –n 150000 -t get,set
3、测试Redis pipeline,设置-P参数为当前系统核数
测试命令:redis-benchmark -h redis-XXX.com -r 50 -c 100 –n 150000 -t get,set -P 16
4、手动调试确定连接数和发起请求书的最优区间范围,通过多次增加连接数和请求数的数值,从结果中选择较优结果情况下的连接数和请求数(比如 连接数300,请求数10w)
5、基于以上获取的请求数,设置-n参数为15w,在连接数相近的区间内(200–500),编写获取最优连接数的测试脚本,如下:
 

#!/bin/bash
connect=(200 250 300 350 400)

n=2000000

host1=redis-XXX.com

host2=ip
for c in \(<span >{<!-- --></span>connect<span >[</span>@<span >]</span><span >}</span>:
<span >do</span>
	<span >## redis-onekey</span>
	<span >echo</span> <span >"redis-benchmark -h <span >\)host1 -r 1 -c \(c</span> -n <span >\)n  -t get,set" >> ./results/redis-onekey.log

redis-benchmark -h \(host1</span> <span >-</span>r 1 <span >-</span>c <span >\)c -n \(n</span>  <span >-</span>t get<span >,</span><span >set</span> >> <span >.</span><span >/</span>results<span >/</span>redis<span >-</span>onekey<span >.</span>log
	<span >## redis-keys</span>
	<span >echo</span> <span >"redis-benchmark -h <span >\)host1 -r 100 -c \(c</span> -n <span >\)n -t get,set" >>./results/redis-keys.log

redis-benchmark -h \(host1</span> <span >-</span>r 100 <span >-</span>c <span >\)c -n \(n</span> <span >-</span>t get<span >,</span><span >set</span> >><span >.</span><span >/</span>results<span >/</span>redis<span >-</span>keys<span >.</span>log
	<span >## redis-pipeline</span>
	<span >echo</span> <span >"redis-benchmark -h <span >\)host1 -r 1 -c \(c</span> -n <span >\)n -t get,set -P 16" >>./results/redis-pipeline.log

redis-benchmark -h \(host1</span> <span >-</span>r 1 <span >-</span>c <span >\)c -n \(n</span> <span >-</span>t get<span >,</span><span >set</span> <span >-</span>P 16 >><span >.</span><span >/</span>results<span >/</span>redis<span >-</span>pipeline<span >.</span>log
	<span >## server-onekey</span>
	<span >echo</span> <span >"redis-benchmark -h <span >\)host2 -r 1 -c \(c</span> -n <span >\)n -t get,set" >>./results/server-onekey.log

redis-benchmark -h \(host2</span> <span >-</span>r 1 <span >-</span>c <span >\)c -n \(n</span> <span >-</span>t get<span >,</span><span >set</span> >><span >.</span><span >/</span>results<span >/</span>server<span >-</span>onekey<span >.</span>log
	<span >##server-keys</span>
	<span >echo</span> <span >"#dsg-keys /n redis-benchmark -h <span >\)host2 -r 100 -c \(c</span> -n <span >\)n -t get,set ">>./results/server-keys.log

redis-benchmark -h \(host2</span> <span >-</span>r 100 <span >-</span>c <span >\)c -n \(n</span> <span >-</span>t get<span >,</span><span >set</span> >><span >.</span><span >/</span>results<span >/</span>server<span >-</span>keys<span >.</span>log
	<span >## server-pipeline</span>
	<span >echo</span> <span >"redis-benchmark -h <span >\)host2 -r 1 -c \(c</span> -n <span >\)n -t get,set -P 16" >>./results/server-pipeline.log

redis-benchmark -h \(host2</span> <span >-</span>r 1 <span >-</span>c <span >\)c -n $n -t get,set -P 16 -q >>./results/server-pipeline.log

done

6、执行脚本之后,通过log日志,记录不同连接数下的QPS和lantency的结果,如下所示:

测试结果

        并发从200-400,set/get即读写性能均可满足要求。

参考:

https://redis.io/docs/latest/operate/oss_and_stack/management/optimization/benchmarks/#factors-impacting-redis-performance

https://zhuanlan.zhihu.com/p/76788470

https://www.cnblogs.com/wy123/p/14180499.html

二、Redis性能优化方案


2.1、硬件配置优化

网络优化:

  1. 使用高性能网络设备: 确保Redis服务器和客户端之间的网络连接是高性能的,采用千兆以太网或更高速的网络设备。
  2. 调整内核参数: 针对高负载的情况,优化操作系统的网络相关内核参数,包括调整TCP连接数、缓冲区大小等。
  3. 使用连接池: 在客户端使用连接池,避免频繁地打开和关闭网络连接,减少连接的建立和断开开销。

内存优化:

  1. 使用高性能内存条:选择具有较高速度和低延迟的内存条。
  2. 增加内存容量: Redis是一个内存数据库,更多的内存通常意味着更好的性能,特别是当你的数据集逐渐增大时。确保服务器上安装了足够的内存,以满足数据存储的需求。
  3. 合理设置maxmemory参数: 设置maxmemory参数,防止Redis使用过多内存导致系统出现性能问题。
  4. 使用内存碎片整理: 定期查找和整理内存碎片。


2.2、参数配置优化

Redis的性能参数需要结合实际的应用场景来调整,以达到最佳的性能表现。

  1. 设置合理的 maxmemory 参数:maxmemory 参数用于限制 Redis 内存的使用量。如果设置过小,可能会导致 Redis 频繁 LRU 淘汰,影响性能。如果设置过大,可能会导致 Redis 内存不足,导致服务不可用。
  2. 设置合理的 maxmemory-policy 参数:maxmemory-policy 参数用于指定 Redis 在内存不足时采取的策略。
  3. 设置合理的 timeout 参数:timeout 参数用于指定客户端连接超时时间。如果设置过小,可能会导致客户端连接频繁断开,影响性能。如果设置过大,可能会导致客户端连接时间过长,影响性能。
  4. 设置合理的 loglevel 参数:loglevel 参数用于指定 Redis 日志级别。如果设置过高,可能会导致 Redis 日志输出过多,影响性能。如果设置过低,可能会导致重要的日志信息丢失,影响排错。
  5. 设置持久化方式
  6. 调整线程数
  7. 调整redis数据结构:优化Redis数据结构可以提高Redis的性能和可用性。
    1. 使用Hash数据结构存储数据
    2. 使用Sorted Set数据结构存储有序数据
    3. 使用BitMap数据结构存储二进制数据

2.3、数据结构优化

Redis支持多种数据结构,每种数据结构都有自己的特点和适用场景。选择合适的数据结构可以节省内存空间,减少网络开销,提高查询速度。例如:

  1. 避免使用过大的键名或值,因为它们会占用更多的内存和网络带宽。
  2. 避免使用过多的层级结构,因为它们会增加查询的复杂度和开销。
  3. 避免使用过于稀疏的数据结构,因为它们会浪费内存空间。例如,如果你需要存储一个大量空值的矩阵,可以考虑使用压缩列表或位图等更紧凑的数据结构。

2.4、使用合理的过期策略

Redis 的过期策略可以有效提升 Redis 的性能。以下是一些使用合理的过期策略优化 Redis 性能的技巧:

  1. 根据数据使用情况设置合理的过期时间:过期时间设置过短,会导致 Redis 频繁进行 LRU 淘汰,影响性能。过期时间设置过长,会导致 Redis 内存使用率过高,影响性能。
  2. 根据数据访问频率设置合理的过期策略:对于经常访问的数据,可以设置较长的过期时间。对于不经常访问的数据,可以设置较短的过期时间。
  3. 使用惰性过期:惰性过期是指 Redis 在访问键时才判断键是否过期。惰性过期可以降低 LRU 淘汰对性能的影响。

2.5、使用合适的持久化机制

  1. RDB持久化是指定期将Redis内存中的数据快照保存到磁盘上,它的优点是文件紧凑,恢复速度快,适合做备份和灾难恢复。它的缺点是可能会丢失最近一次快照之后的数据,以及在执行快照时会占用一定的CPU和内存资源。
  2. AOF持久化是指将Redis执行的每个写操作记录到一个日志文件中,它的优点是数据实时性高,可以保证数据的完整性和一致性。它的缺点是文件较大,恢复速度慢,以及在追加日志时会增加磁盘IO的压力。
  3. RDB + AOF:在同一个实例中可以组合 AOF 和 RDB一起使用,也就是我们常说的混合模式。

如果你的业务对数据的实时性要求较高,或者不能容忍数据的丢失,可以选择AOF持久化,或者同时开启RDB和AOF持久化,让AOF优先于RDB恢复数据。如果你的业务对数据的实时性要求不高,或者可以容忍一定的数据丢失,你可以选择RDB持久化,或者关闭持久化,只依赖主从复制来保证数据的可用性。

2.6、使用合理的集群方案

Redis 集群可以有效提升 Redis 的性能。

  1. 主从复制模式:主从复制模式是最简单的集群模式。在主从复制模式中,一个节点作为主节点,其他节点作为从节点。主节点负责写入数据,从节点负责读取数据也就是我们说的读写分离。
  2. 哨兵模式:哨兵模式是一种高可用的集群模式。在哨兵模式中,每个节点都作为哨兵节点。哨兵节点负责监控主节点的状态,如果主节点发生故障,哨兵节点会自动选举出新的主节点。哨兵模式也适用于读写分离。
  3. 集群模式:集群模式是一种负载均衡的集群模式。在集群模式中,每个节点都平等,可以进行写入和读取数据。如果在成本允许的情况下使用此集群模式可以大大的提升Redis的性能。

2.7 优化Redis客户端

        优化Redis客户端可以提高Redis的性能和可用性。

以下是常用的Redis客户端优化项:

  • 使用连接池管理连接
  • 使用异步IO操作
  • 使用Pipeline批量操作

三、Redis规范

1. 键值对使用规范


1. Key的命名规范

Redis的Key命名规范可以根据实际需求和个人偏好进行定义,但以下是一些常见的命名规范和最佳实践:

  1. 简洁明了:Key应该简洁明了,能够清晰表达其含义。避免使用过长或过于复杂的Key名称,以减少存储空间和提高性能。
  2. 使用命名空间:为了避免Key之间的冲突,可以使用命名空间来对Key进行分类或分组。例如,可以使用"namespace:key"的形式,如"user:123"和"order:456"。
  3. 使用冒号分隔层级:使用冒号作为层级分隔符,以便在Key命名中表示层级关系。例如,可以使用"category:books"和"category:movies"来表示不同类别下的数据。
  4. 避免使用特殊字符:避免在Key命名中使用特殊字符,如空格、制表符或换行符等,以免引起解析或处理上的困扰。
  5. 使用一致的命名风格:选择一种命名风格,并在整个应用程序中保持一致。例如,可以选择使用全小写字母、使用下划线作为单词分隔符,或者使用驼峰式命名。
  6. 可读性和可维护性:选择具有可读性和可维护性的Key名称,以便其他开发人员能够轻松理解和操作。避免使用过于简化或缩写的Key名称,除非在特定情况下确实需要。
  7. 规避命名冲突:确保Key名称与其他数据存储系统或数据库中的其他命名不冲突,以免造成混淆和错误。

总之,好的Key命名应该简洁、明了、具有可读性和可维护性,并且能够清晰地表示其含义和关系。根据具体情况,可以根据以上建议进行命名,也可以根据团队或项目的规范进行定制化命名。

2. 避免使用 bigkey

确实,避免使用"bigkey"是一个良好的实践。在Redis中,"bigkey"指的是占用大量内存空间的Key,这可能会对性能和资源消耗产生负面影响。

2.1. "bigkey"的导致的问题

  1. 内存消耗:"bigkey"占用大量内存,特别是当使用Redis的RDB持久化或AOF日志持久化时。如果大量的内存被用于存储单个Key,会导致Redis实例的内存不足,影响其他Key的存储和读取。
  2. 读写性能:对"bigkey"的读写操作需要更多的时间和资源。当需要读取或更新一个大的Key时,Redis需要花费更多的时间来序列化和反序列化数据,以及在网络传输中传递更多的字节。
  3. 过期处理:如果一个"bigkey"设置了过期时间,当该Key过期时,Redis可能会阻塞一段时间来删除它,从而影响其他操作的执行。

2.2 避免"bigkey"问题解决方法
2.2 1. 数据分片
将大的数据拆分成更小的片段,存储在多个Key中。这样可以均匀地分散数据,减少单个Key的大小。
是的,数据分片是一种常用的方法,用于将大的数据拆分成更小的片段,并将它们存储在多个Key中。这样可以均匀地分散数据,减少单个Key的大小,从而提高Redis的性能和资源利用率。

数据分片的指导原则:

  1. 分片策略:选择合适的分片策略是非常重要的。一种常见的方法是使用哈希函数,将数据的某个唯一标识(如ID或属性)映射到不同的Key上。这样可以确保相同标识的数据总是存储在同一个分片中。
  2. 分片数量:决定分片数量时需要权衡。较少的分片数量可以减少管理和维护的复杂性,但可能导致某些分片过于庞大,仍然存在"bigkey"的问题。较多的分片数量可以更均匀地分散数据,但会增加一些额外的开销和复杂性。
  3. 分片映射:维护一个分片映射表,用于记录数据的唯一标识与对应分片的映射关系。这样可以根据标识快速定位到正确的分片,并进行读取和操作。
  4. 一致性哈希:一致性哈希算法是一种常用的数据分片算法,它可以在增加或减少分片时最小化数据迁移的量。一致性哈希可以提供较好的负载均衡和容错性。

2.2.2. 数据压缩
对于大的数据,可以在存储之前进行压缩,以减少内存占用和网络传输的开销。Redis提供了一些压缩算法,如LZF和Snappy。
确实,使用高效的序列化方法和压缩方法可以在Redis中存储和传输数据时提高性能和节省存储空间。

3. 使用高效序列化方法和压缩方法


3.2.1. 序列化方法
选择高效的序列化方法可以将数据转换为字节序列,并在存储和传输过程中提供更高的效率。在Redis中,常见的序列化方法包括JSON、MessagePack、Protocol Buffers等。根据数据的特性和需求,选择适合的序列化方法。不同的序列化方法,在序列化速度和数据序列化后的占用内存空间这两个方面,效果是不一样的。比如说,protostuff 和 kryo 这两种序列化方法,就要比 Java 内置的序列化方法(java-build-in-serializer)效率更高。
常见的序列化方法

  1. JSON适用于数据结构相对简单,对可读性和跨平台兼容性要求较高的场景。
  2. MessagePack是一种高效的二进制序列化格式,可以将数据紧凑地序列化为字节序列。它具有较高的序列化和反序列化性能,并支持多种编程语言。MessagePack序列化方法在Redis中可以节省存储空间和提高性能,但可读性较差。它适用于对存储空间和传输效率要求较高的场景。
  3. Protocol Buffers是一种语言无关、平台无关的序列化格式,由Google开发。它使用描述性的接口定义语言(IDL)来定义数据结构,并生成相应的代码库,以实现高效的序列化和反序列化操作。ProtocolBuffers在Redis中可以提供较高的性能和较小的序列化尺寸,但使用它需要额外的代码生成步骤。ProtocolBuffers适用于对性能和存储空间都有较高要求的场景。

三种序列化方式的比较:

3.2.2. 压缩方法
对于大量重复或冗余的数据,使用压缩方法可以减少存储空间和网络传输的开销。Redis提供了一些内置的压缩算法,如LZF压缩算法和Snappy压缩算法。可以根据数据的特点选择合适的压缩方法。

当处理包含大量重复或冗余数据的场景时,使用压缩方法可以显著减少存储空间和网络传输开销。以下是两个内置的压缩算法示例,可以在Redis中使用:

1. LZF压缩算法:
LZF是一种快速的无损压缩算法,适用于需要高压缩速度和较低压缩率的场景。它在压缩和解压缩过程中消耗的CPU资源相对较少。LZF算法在Redis中被广泛使用,可以通过开启zstd选项来启用。
假设在Redis中存储了大量的重复文本数据,例如日志消息,这些消息可能存在大量的重复行。使用LZF压缩算法可以显著减少存储空间和传输开销。
代码示例
pom.xml文件中添加以下依赖:

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>
<dependency>
    <groupId>com.ning</groupId>
    <artifactId>compress-lzf</artifactId>
    <version>1.0.3</version>
</dependency>

使用LZFEncoder.encode()方法对字节数组进行压缩,然后将压缩后的字节数组保存到Redis中。 使用LZFDecoder.decode()方法对其进行解压缩。

import redis.clients.jedis.Jedis;
import com.ning.compress.lzf.LZFEncoder;
import com.ning.compress.lzf.LZFDecoder;

public class RedisLZFExample {
    public static void main(String[] args) throws Exception {
        // Create a connection to Redis
        Jedis jedis = new Jedis("localhost");

        String str = "日志数据: This is a repeated message.";
        byte[] original = str.getBytes();

        // Compress the bytes
        byte[] compressed = LZFEncoder.encode(original);

        // Save the compressed data in Redis
        jedis.set("myKey".getBytes(), compressed);

        // Retrieve the compressed data from Redis
        byte[] retrieved = jedis.get("myKey".getBytes());

        // Decompress the bytes
        byte[] decompressed = LZFDecoder.decode(retrieved);

        // Convert the decompressed bytes back to a String
        String result = new String(decompressed, "UTF-8");

        System.out.println("Original:    " + str);
        System.out.println("Decompressed:" + result);

        jedis.close();
    }
}

2. Snappy压缩算法:
Snappy是一种快速压缩算法,适用于需要高压缩率和较低压缩速度的场景。它在压缩和解压缩过程中相对较快,但相对于LZF算法,压缩率较高。Snappy算法在Redis中也可用,可以通过开启snappy选项来启用。设在Redis中存储了大量的图像文件,这些文件可能存在相似的图像块或者元数据。使用Snappy压缩算法可以大幅度减少存储空间和网络传输开销。

在选择压缩方法时,需要根据数据的特点和应用需求进行评估。如果对压缩速度要求较高且可以容忍较低的压缩率,可以选择LZF算法。如果需要更高的压缩率且可以接受稍微较慢的压缩速度,则可以选择Snappy算法。

需要注意的是,压缩算法并非适用于所有类型的数据。对于已经高度压缩的数据(如已经使用了其他压缩算法的数据)或者具有较低的冗余性的数据,压缩可能并不会产生显著的效果。因此,在应用压缩算法之前,应仔细评估数据的特点和预期的效果。

4 使用整数对象共享池


我觉得这个规范意义不是很大。Redis使用了一种名为整数对象共享池的技术来优化内存使用。这种技术的主要想法是将常用的小整数预先创建并存储在一个内部池中,当需要创建这些整数时,就直接从池中获取,而不是每次都创建新的对象。

这种技术在Redis的许多功能中都有使用,例如在计数器、哈希表的大小和列表的长度等地方。

在Redis源码中,这个整数对象共享池被定义为一个大小为10000的数组,数组的索引即为对应的整数值,数组的元素为对应的整数对象。

当需要一个整数对象时,Redis会首先检查这个整数是否在共享池的范围内(0-9999),如果在范围内就直接从共享池中获取,否则才创建新的整数对象。

这种技术对内存优化并减少了对象创建的次数有很大的帮助,但是对于开发者来说是透明的,开发者无需关心这个过程,Redis会自动处理。这种优化技术只适用于小整数,对于大整数或者浮点数,Redis并没有提供共享池的机制。

2. 数据保存规范

2.1. 使用 Redis 保存热数据

Redis是一个内存数据库,读写速度非常快,适合存储访问频繁的热数据。例如,可以将用户的会话信息、热门商品的信息等存储在Redis中,以提高系统的响应速度。

例如,对于一个电商网站,热门商品的销售数据是经常需要查询的热数据。将这些数据存储在Redis中,当用户查询这些商品的销售数据时,可以直接从Redis中获取,而不需要去数据库中查询,大大提高了响应速度。

2.2. 不同的业务数据分实例存储

为了保证数据的独立性和安全性,不同的业务数据应该存储在不同的Redis实例中。这样,即使某个实例出现问题,也不会影响到其他的业务数据。

例如,一个公司可能有多个业务线,如用户管理、订单管理、商品管理等,每个业务线的数据应该存储在不同的Redis实例中。不同业务线的数据隔离,可以降低数据泄露的风险,避免数据混淆。

2.3. 在数据保存时,要设置过期时间

Redis的数据都是存储在内存中的,如果数据量过大,可能会导致内存溢出。因此,在保存数据时,应该设置一个合理的过期时间,以自动清理不再需要的数据。同时,设置过期时间也可以防止数据过期,保证数据的实时性。

例如,对于用户的登陆信息,我们可以设置其在Redis中的过期时间为30分钟。这样,如果用户在30分钟内没有任何操作,Redis会自动删除这些数据,释放内存。同时,也可以避免用户的登陆信息被他人利用

2.4. 控制 Redis 实例的容量

每个Redis实例都有其最大的内存容量,超过这个容量,Redis可能会出现问题。因此,应该定期监控Redis实例的内存使用情况,及时清理不需要的数据,控制Redis实例的容量。
将Redis单实例的内存大小设置在2~6GB之间,可以在保证性能的同时,避免在进行RDB快照或主从集群数据同步时产生过大的延迟。这样的设置可以确保Redis在处理正常请求时,不会因为数据备份或同步而产生阻塞,从而提高系统的整体性能和稳定性。

比如,假设我们的服务器内存为16GB,为了保证Redis的正常运行,我们应当将Redis实例的最大内存限制设置在12GB以下,以防止内存溢出。我们还应当定期检查Redis实例的内存占用情况,如果内存占用接近最大限制,就应当及时清理不必要的数据。

3. 命令使用规范


3.1 线上禁用部分命令


在线上环境中,有些Redis命令可能会对系统的稳定性和性能产生影响,因此我们应当禁用这些命令。例如,我们可以禁用FLUSHDB和FLUSHALL命令,以防止误操作导致的数据丢失。另外,我们也可以禁用DEBUG和CONFIG命令,以防止未授权的用户修改系统配置。

3.2 慎用 MONITOR 命令


MONITOR命令可以用来实时监控Redis服务器的所有请求,但是这个命令会消耗大量的CPU和网络资源。因此,在线上环境中,我们应当慎用MONITOR命令。如果我们需要监控Redis服务器的性能,可以使用INFO命令或者使用专门的监控工具。

3.3 慎用全量操作命令


全量操作命令,如KEYS、SMEMBERS等,会返回大量的数据,可能会导致网络延迟和CPU占用过高。在大数据量的情况下,这些命令可能会阻塞Redis服务器,影响其他命令的执行。因此,我们应当慎用全量操作命令。如果我们需要获取大量的数据,可以使用SCAN、SSCAN等命令,这些命令可以分批次获取数据,避免阻塞服务器。

下面是一位大牛整理的规范,我做了一些说明。

4. 业务层面:

  1. key 的长度尽量短:这个是因为 Redis 中的 key 是利用字典数据结构存储的,key 的大小会直接影响 Redis 的内存使用量,过长的 key 会占用更多的内存空间。
  2. 避免 bigkey:bigkey 是指大小超过 10kb 或者列表、集合、有序集合、哈希元素个数超过 5000 的 key。Redis 是单线程的,处理 bigkey 需要消耗很多 CPU 时间,会导致其他命令的阻塞。
  3. 4.0+版本建议开启 lazy-free:对内存回收策略进行优化,当删除大量数据时,Redis 会将内存回收操作放在后台线程中进行,避免主线程被阻塞。
  4. 把 Redis 当作缓存使用,设置过期时间:这样可以防止内存被大量数据占满,导致服务无法正常使用。
  5. 不使用复杂度过高的命令:这些命令的时间复杂度往往比较高,会消耗大量的 CPU 时间,影响 Redis 的性能。
  6. 查询数据尽量不一次性查询全量,写入大量数据建议分多批写入:这样可以防止一次性操作大量数据导致的 Redis 阻塞。
  7. 批量操作建议 MGET/MSET 替代 GET/SET,HMGET/HMSET 替代 HGET/HSET:批量操作可以减少网络延迟,提高 Redis 性能。
  8. 禁止使用 KEYS/FLUSHALL/FLUSHDB 命令:这些命令会阻塞 Redis,影响服务的性能。
  9. 避免集中过期 key:如果大量的 key 集中在某一时间过期,会导致 Redis 阻塞。
  10. 根据业务场景选择合适的淘汰策略:比如 volatile-lru(从设置了过期时间的 key 中选择最少使用的 key 淘汰)等。

5. 运维层面:

  1. 按业务线部署实例:避免多个业务线混合部署,在出问题时,影响范围更小。
  2. 保证机器有足够的 CPU、内存、带宽、磁盘资源:这些都是 Redis 正常运行的基础。
  3. 建议部署主从集群,并分布在不同机器上:保证数据的稳定性,同时减少单点故障风险。
  4. 主从节点所部署的机器各自独立,尽量避免交叉部署:以免一个节点出问题,影响到其他节点。
  5. 推荐部署哨兵集群实现故障自动切换:自动切换主从,保证系统的高可用。
  6. 提前做好容量规划,防止主从全量同步时,实例使用内存突增导致内存不足:避免因内存不足导致的服务故障。
  7. 做好机器 CPU、内存、带宽、磁盘监控:及时发现问题,防止服务故障。
  8. 实例设置最大连接数:防止过多客户端连接导致实例负载过高,影响服务性能。
  9. 单个实例内存建议控制在 10G 以下:大实例在主从全量同步、备份时有阻塞风险。
  10. 设置合理的 slowlog 阈值,并对其进行监控:slowlog 过多可能意味着存在性能问题。
  11. 设置合理的 repl-backlog,降低主从全量同步的概率:主从全量同步往往会消耗大量资源,影响服务性能。
  12. 设置合理的 slave client-output-buffer-limit,避免主从复制中断情况发生。
  13. 推荐在从节点上备份,不影响主节点性能:备份任务往往会消耗大量资源,影响服务性能。
  14. 不开启 AOF 或开启 AOF 配置为每秒刷盘,避免磁盘 IO 拖慢 Redis 性能:AOF 会增加磁盘 IO,影响服务性能。
  15. 调整 maxmemory 时,注意主从节点的调整顺序,顺序错误会导致主从数据不一致:保证数据的一致性。
  16. 对实例部署监控,采集 INFO 信息时采用长连接,避免频繁的短连接:频繁的网络连接会消耗大量资源,影响服务性能。
  17. 做好实例运行时监控,重点关注 expired_keys、evicted_keys、latest_fork_usec:这些指标反映了 Redis 的运行状况,短时突增可能会有阻塞风险。
  18. 扫描线上实例时,记得设置休眠时间,避免过高 OPS 产生性能抖动:扫描操作往往会消耗大量资源,影响服务性能。

  • 20
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-无-为-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值