Redis 6.0中将处理过程中最耗时的Socket读取、请求解析、单独用一个线程来处理,剩下的命令执行操作仍然由单线程来完成和内存的数据交互,这样一来,网络IO操作就变成了多线程了,但是核心部分仍然是线程安全的,如图4-9所示。
图4-9为什么说Redis6.0是一个特殊的多线程,原因就在这里,Redis主要针对网络IO这块引入了多线程的方式来提升了网络IO性能,但是真正执行命令的操作仍然是由主线程来完成。因此,总的来说,我们仍然可以说Redis是单线程模型。
Redis 6.0如何开启多线程Redis 6.0默认多线程是禁止的,也就是仍然只是使用主线程来完成网络IO,如果需要开启,则修改redis.conf配置文件中的如下属性
# 默认是关闭,设置为yes打开 io-threads-do-reads no #默认线程数量是4,官方建议是4核机器上设置为2~3个,8核机器上设置6个 io-threads 4 引入多线程之后的性能提升图4-20是美团技术团队使用阿里云服务器压测GET/SET命令在4个线程IO时性能上的对比结果,可以明显的看到,Redis 在使用多线程模式之后性能大幅提升,达到了一倍。
Redis Server 阿里云 Ubuntu 18.04 , 8CPU 2.5GHZ,8G内存,主机型号: ecs.ic5.2xlarge
Redis Benchmark client: 阿里云 Unbuntu 18.04 , 8CPU 2.5GHZ,8G内存,主机型号:ecs.ic5.2xlarge
图4-20 内存回收策略很多同学了解了Redis的好处之后,于是把任何数据都往Redis中放,如果使用不合理很容易导致数据超过Redis的内存,这种情况会出现什么问题呢?
Redis中有很多无效的缓存,这些缓存数据会降低数据IO的性能,因为不同的数据类型时间复杂度算法不同,数据越多可能会造成性能下降
随着系统的运行,redis的数据越来越多,会导致物理内存不足。通过使用虚拟内存(VM),将很少访问的数据交换到磁盘上,腾出内存空间的方法来解决物理内存不足的情况。虽然能够解决物理内存不足导致的问题,但是由于这部分数据是存储在磁盘上,如果在高并发场景中,频繁访问虚拟内存空间会严重降低系统性能。
所以遇到这类问题的时候,我们一般有几种方法。
对每个存储到redis中的key设置过期时间,这个根据实际业务场景来决定。否则,再大的内存都会虽则系统运行被消耗完。
增加内存
使用内存淘汰策略。
设置Redis能够使用的最大内存在实际生产环境中,服务器不仅仅只有Redis,为了避免Redis内存使用过多对其他程序造成影响,我们一般会设置最大内存。
Redis默认的最大内存maxmemory=0,表示不限制Redis内存的使用。我们可以修改redis.conf文件,设置Redis最大使用的内存。
# 单位为byte maxmemory <bytes> 2147483648(2G)如何查看当前Redis最大内存设置呢,进入到Redis-Cli控制台,输入下面这个命令。
config get maxmemory当Redis中存储的内存超过maxmemory时,会怎么样呢?下面我们做一个实验
在redis-cli控制台输入下面这个命令,把最大内存设置为1个字节。
config set maxmemory 1
通过下面的命令存储一个string类型的数据
set name mic
此时,控制台会得到下面这个错误信息
(error) OOM command not allowed when used memory > 'maxmemory'. 使用内存淘汰策略释放内存设置了maxmemory的选项,redis内存使用达到上限。可以通过设置LRU算法来删除部分key,释放空间。默认是按照过期时间的,如果set时候没有加上过期时间就会导致数据写满maxmemory。
Redis中提供了一种内存淘汰策略,当内存不足时,Redis会根据相应的淘汰规则对key数据进行淘汰。 Redis一共提供了8种淘汰策略,默认的策略为noeviction,当内存使用达到阈值的时候,
所有引起申请内存的命令会报错。
volatile-lru,针对设置了过期时间的key,使用lru算法进行淘汰。
allkeys-lru,针对所有key使用lru算法进行淘汰。
volatile-lfu,针对设置了过期时间的key,使用lfu算法进行淘汰。
allkeys-lfu,针对所有key使用lfu算法进行淘汰。
volatile-random,从所有设置了过期时间的key中使用随机淘汰的方式进行淘汰。
allkeys-random,针对所有的key使用随机淘汰机制进行淘汰。
volatile-ttl,删除生存时间最近的一个键。
noeviction,不删除键,值返回错误。