中间件|Redis

1.配置文件 1.网络相关配置#NETWORK# 1.bind

bind 127.0.0.1 -::1

默认情况bind=127.0.0.1 只能接受本机的访问请求,正常应该注释掉
如果开启了protected-mode,那么在没有设定bind ip且没有设密码的情况下,Redis只允许接受本机的响应
2.protected-mode
protected-mode yes
本机保护模式
正常我们应该设置这一项为yes,然后给reids加密码(requirepass)或者bind我们自己的ip
3.port
port 6379

指定redis服务器的端口 默认6379
4.tcp-backlog
tcp-backlog 511

默认511
设置tcp的backlog,backlog其实是一个连接队列,backlog队列总和=未完成三次握手队列 + 已经完成三次握手队列。
注意Linux内核会将这个值减小到/proc/sys/net/core/somaxconn的值(128),所以需要确认增大/proc/sys/net/core/somaxconn和/proc/sys/net/ipv4/tcp_max_syn_backlog(128)两个值来达到想要的效果。
可以在/etc/sysctl.conf添加net.core.somaxconn = 2048和net.ipv4.tcp_max_syn_backlog = 2028
然后然后在终端中执行sysctl -p
5.timeout
timeout 0

一个空闲的客户端维持多少秒会关闭,0表示关闭该功能。即永不关闭。
这个应该设置为多少呢?后期找到答案再来改吧
6.tcp-keepalive
tcp-keepalive 300

对访问客户端的一种心跳检测,每隔n秒检测一次。默认300
2.通用#GENERAL# 1.daemonize
daemonize yes

yes 设置为后台启动 必须开启
2.pidfile
pidfile /var/run/redis_6379.pid

存放pid文件的位置,每个实例会产生一个不同的pid文件
3.loglevel
loglevel notice

Redis总共支持四个级别:debug、verbose、notice、warning,默认为notice
生产环境选择notice 或者warning
4.logfile
logfile ""

日志文件名称,默认不开启
logfile “/home/myredis/log/redis.log” 指定log文件路径,必须创建文件夹,文件redis会自动生成
5.databases
databases 16

设定库的数量 默认16,默认数据库为0,可以使用SELECT 命令在连接上指定数据库id
3.安全相关#SECURITY 1.requirepass
requirepass 123456

4.limits限制 1.maxclients
maxclients 10000

设置redis同时可以与多少个客户端进行连接。默认值为10000,如果达到了此限制,redis则会拒绝新的连接请求,并且向这些连接请求方发出“max number of clients reached”以作回应。
2.maxmemory
maxmemory

设置redis可以使用的内存量。一般为总内存的3/4,一旦到达内存使用上限,redis将会试图移除内部数据,移除规则可以通过maxmemory-policy来指定。
如果redis无法根据移除规则来移除内存中的数据,或者设置了“不允许移除”,那么redis则会针对那些需要申请内存的指令返回错误信息,比如SET、LPUSH等。
3.maxmemory-policy
达到内存上限时的移除策略,默认不进行移除,写操作会返回错误
maxmemory-policy noeviction

  • volatile-lru:使用LRU算法移除key,只对设置了过期时间的键;(最近最少使用)
  • allkeys-lru:在所有集合key中,使用LRU算法移除key
  • volatile-random:在过期集合中移除随机的key,只对设置了过期时间的键
  • allkeys-random:在所有集合key中,移除随机的key
  • volatile-ttl:移除那些TTL值最小的key,即那些最近要过期的key
  • noeviction:不进行移除。针对写操作,只是返回错误信息
  • volatile-lfu:设置了过期时间的key使用LFU算法淘汰;
  • allkeys-lfu:所有key使用LFU算法淘汰;
    具体使用哪种策略,我们需要根据具体的业务场景来配置。一般最常使用的是 volatile-lru和volatile-lfu 淘汰策略,它们的处理逻辑是,每次从实例中随机取出一批 key(这个数量可配置maxmemory-samples),然后淘汰一个最少访问的 key,之后把剩下的 key 暂存到一个池子中,继续随机取一批 key,并与之前池子中的 key 比较,再淘汰一个最少访问的 key。以此往复,直到实例内存降到 maxmemory 之下。
需要注意的是,Redis 的淘汰数据的逻辑与删除过期 key 的一样,也是在命令真正执行之前执行的,也就是说它也会增加我们操作 Redis 的延迟,而且,写 OPS 越高,延迟也会越明显。
LRU:最近最少使用,原则是近期被访问过,那么以后被访问的可能性比较高,注重最近访问过,不考虑次数,可能存在不常用的key近期刚好访问过一次,那么也不会被删除的问题。
LFU:最不经常使用,原则是如果数据被访问过多次,那么以后被访问的可能性比较高,解决了LRU的问题,多次使用过的key才不会被删除。
上面是内存满了的情况下,执行的淘汰策略,正常设置了过期时间的key,redis默认会采用惰性删除 + 定期删除的方式。
惰性删除:key到期不会删除,再次访问这个key时会进行删除,并返回空
定期删除:根据hz的值循环进行定期删除,默认100ms执行一次,随机选取maxmemory-samples设置的值的数量的key进行检测,过期的话就进行删除。
4.maxmemory-samples
样本数量
maxmemory-samples 5

设置样本数量,LRU算法和最小TTL算法都并非是精确的算法,而是估算值,所以你可以设置样本的大小,redis默认会检查这么多个key并选择其中LRU的那个。
一般设置3到7的数字,数值越小样本越不准确,但性能消耗越小。
5.hz
每秒执行几次定期删除
hz 10

默认10,也就是100ms执行一次定期删除。
5.持久化相关配置 1.RDB
在指定的时间间隔内将内存中的数据集快照写入磁盘
Redis会单独创建(fork)一个子进程来进行持久化(扩大一倍,占内存),会先将数据写入到 一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。 整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能 如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。
数据恢复方式
将数据存到rdb文件后,关闭服务器,重新启动服务器时会主动读取rdb中的记录,将保存的数据恢复。(如果同时开了AOF,则不会读取这个rdb文件,会去读取aof文件,实现数据恢复)
1.#SNAPSHOTTING# 1.save
save 30 3

在30秒内有三次修改,就将key value保存到硬盘
默认
save 3600 1 save 300 100 save 60 10000

60s改一万次,600s改100次,3600s改1次
2.stop-writes-on-bgsave-error
#当Redis无法写入磁盘的话,直接关掉Redis的写操作。推荐yes. stop-writes-on-bgsave-error yes

3.rdbcompression
#对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis会采用LZF算法进行压缩。推荐yes rdbcompression yes

4.rdbchecksum
#在存储快照后,还可以让redis使用CRC64算法来进行数据校验, #但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能 #推荐yes. rdbchecksum yes

5.dbfilename
#文件名 dbfilename dump.rdb

6.dir rbd文件保存路径 默认src下
#文件路径 src下 dir ./

2.AOF
默认不开启
以日志的形式来记录每个写操作(增量保存),将Redis执行过的所有写指令记录下来(读操作不记录), 只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作
1.#APPEND ONLY MODE# 控制开启AOF
1.appendonly
appendonly no

2.appendfilename 指定文件名
appendfilename "appendonly.aof"

3.appendfsync AOF同步频率设置
appendfsync everysec

appendfsync always
始终同步,每次Redis的写入都会立刻记入日志;性能较差但数据完整性比较好
appendfsync everysec
每秒同步,每秒记入日志一次,如果宕机,本秒的数据可能丢失。
appendfsync no
redis不主动进行同步,把同步时机交给操作系统。
4.no-appendfsync-on-rewrite AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后再rename),redis4.0版本后的重写,是指上就是把rdb 的快照,以二级制的形式附在新的aof头部,作为已有的历史数据,替换掉原来的流水账操作。
no-appendfsync-on-rewrite=yes
不写入aof文件只写入缓存,用户请求不会阻塞,但是在这段时间如果宕机会丢失这段时间的缓存数据。(降低数据安全性,提高性能)
no-appendfsync-on-rewrite=no
还是会把数据往磁盘里刷,但是遇到重写操作,可能会发生阻塞。(数据安全,但是性能降低)
5.auto-aof-rewrite-percentage&auto-aof-rewrite-min-size 重写触发机制,这两个条件都满足才触发重写
#文件达到100%时开始重写(文件是原来重写后文件的2倍时触发) auto-aof-rewrite-percentage 100 #文件大于64MB开始重写 auto-aof-rewrite-min-size 64mb

3.总结
官方推荐两个都启用。
如果对数据不敏感,可以选单独用RDB。
不建议单独用 AOF,因为可能会出现Bug。
如果只是做纯内存缓存,可以都不用。
两个都启用
在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据, 因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整.
RDB的数据不实时,同时使用两者时服务器重启也只会找AOF文件。那要不要只使用AOF呢?
建议不要,因为RDB更适合用于备份数据库(AOF在不断变化不好备份), 快速重启,而且不会有AOF可能潜在的bug,留着作为一个万一的手段。
因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,只保留save 900 1这条规则。
如果使用AOF,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只load自己的AOF文件就可以了。
代价,一是带来了持续的IO,二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。
【中间件|Redis】只要硬盘许可,应该尽量减少AOF rewrite的频率,AOF重写的基础大小默认值64M太小了,可以设到5G以上。
默认超过原大小100%大小时重写可以改到适当的数值。
2.springboot整合 1.pom
org.springframework.boot spring-boot-starter-data-redis io.lettuce lettuce-core redis.clients jedis org.apache.commons commons-pool2 2.6.0

2.配置文件配置template
@Configuration public class RedisConfig { //自定义RedisTemplate @Bean public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { //为了简化开发 一般自定义template RedisTemplate template = new RedisTemplate<>(); //new 一个Jackson的序列化对象 //Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class); //使用用这个序列化,避免list类型的value序列化错误 GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(); template.setConnectionFactory(redisConnectionFactory); //Json序列化设置 ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); serializer.setObjectMapper(om); //String的序列化 StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); //key采用String的序列化方式 template.setKeySerializer(stringRedisSerializer); //hash的key也采用String的序列化方式 template.setHashKeySerializer(stringRedisSerializer); //value的序列化采用jackson template.setValueSerializer(serializer); //hash的value也采用jackson的序列化 template.setHashValueSerializer(serializer); return template; } }

3.配置文件
#redis spring.redis.host=192.168.56.10 spring.redis.port=6378 #redis设置密码需要配置 #spring.redis.password=123456

4.操作redis 写操作
@Autowired RedisTemplate redisTemplate; @Test void testRedisWrite() { //设置键值对,也可以不加时间,则不会过期 redisTemplate.opsForValue().set("springboot","nice",30, TimeUnit.SECONDS); }

中间件|Redis
文章图片

读操作
@Test void testRedisRead(){ Object springboot = redisTemplate.opsForValue().get("springboot"); log.info("the value:{}",springboot); }

中间件|Redis
文章图片

存对象
@Test void testRedisWriteEntity(){ User user = new User(); user.setName("zhangsan"); user.setAge(18); redisTemplate.opsForValue().set("zhangsan",user); }

中间件|Redis
文章图片

取对象
中间件|Redis
文章图片

对象的话一般存之前转为json,取出来再转为对象
3.redis缓存 在sping系列spring cache中已经写过
4.redis集群 待补充

    推荐阅读