redis内存优化

先了解一个 k-v数据的内存比例
set kk v111
分两个部分。
每个k-v 占据的空间+bucket占据的空间
bucket:每个k-v 数据之间占的内存
大于 k-v 个数的 2的n次方大小的最小值

比如 次处只有1个数据 那么占的大小就是 2的1次方
bucket : 2bit

dictEntry: key ,val ,next 占 24个bit 由jemalloc会分配32字节的内存块

key :存在于 SDS(中) 需要 kk(2)+9 = 11bit
redisObject : 占固定的 16bit

value:SDS 所以 需要 4+9=13bit

redisObject: 占 16bit
综上,一个dictEntry所占据的空间需要32+11+13+16个字节。

优化方式:1.利用jemalloc特性进行优化
2.使用整形/长整形
3.使用和设置共享对象
4.避免过度设计
5.关注内存碎片率

Redis消息模式:1.队列模式 2.发布订阅模式

Redis Stream :

以更抽象的方式建模日志的数据结构。Redis
的streams主要是一个append only(AOF)的数据结构,至少在概念上它是一种在内存中表示的抽象
数据类型,只不过它们实现了更强大的操作,以克服日志文件本身的限制

缓存淘汰策略

LRU原理:last recently used ) 最近最小使用原则

具体:Lid

redis 容器化部署 方案 redis存储优化_Redis


淘汰策略:

redis 提供6种缓存淘汰策略

1. volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的
数据淘汰
2. volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据
淘汰
3. volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘

4. allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
5. allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
6. no-enviction(驱逐):禁止驱逐数据

redis 事物【严格意义上说 redis事务只是个批处理 有隔离性 但是没有原子性

通过四个命令
multi: 开启事物
watch:监控某个key 的变化
unwatch:接触所有的监控
exec:执行所有事物内的命令。
若在一个事物内。当某个被监控的对象的值 发生了变化(其他线程修改导致的)。那么这个事物中的命令队列执行该命令时所有的队列命令被清空
DISCARD:情况事物内的队列的命令
//执行事务,如果其他线程对watchKeys中的value进行修改,则该事务将不会执行

//以上这句话可以理解为:在命令行里新开一个窗口并对watch的值进行了修改  -----》  

//原线程中队列的命令都不生效 代码里就是执行exec后返回null判断

redis与 lua脚本使用

eval “return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}” 2 key1 key2 first second

redis持久化的两种方式:1.RDB(默认) 2.AOF 3.4.0 开始混合模式

RDB方式是通过快照( snapshotting )完成的,当符合一定条件时Redis会自动将内存中的数据进行
快照并持久化到硬盘。

默认情况下 Redis 没有开启 AOF ( append only file )方式的持久化。
开启 AOF 持久化后,每执行一条会更改 Redis 中的数据的命令, Redis 就会将该命令写入硬盘中的
AOF 文件,这一过程显然会降低 Redis 的性能,但大部分情况下这个影响是能够接受的,另外使用较
快的硬盘可以提高 AOF 的性能。AOF是追加写日志文件

Redis主从复制
说明:
主 Redis 中的数据有两个副本( replication )即从 redis1 和从 redis2 ,即使一台 Redis 服务
器宕机其它两台 Redis 服务也可以继续提供服务。
主 Redis 中的数据和从 Redis 上的数据保持实时同步,当主 Redis 写入数据时通过主从复制机制
会复制到两个从 Redis 服务上。
只有一个主 Redis ,可以有多个从 Redis 。
主从复制不会阻塞 master ,在同步数据时, master 可以继续处理 client 请求。
一个 Redis 可以即是主又是从

1)数据同步 全量同步 / 增量同步
2)runid
3) 复制偏移量

Redis哨兵机制

redis 的热点问题

redis 容器化部署 方案 redis存储优化_redis 容器化部署 方案_02

缓存穿透:

是针对数据库和缓存中都没有的数据。场景:当客户端发起查询时,缓存中没有就会去查库,库里也没有,就会返回给客户端错误信息。这样是没问题的,看起来逻辑是完美的,但是这里存在一个漏洞,那就是无论什么样的Key过来查,我们都去接受它的请求,这就可能会被黑客抓住,发起大量请求,并且Key都是我们系统中没有的,库里也查不到对应的值,这样的Key称之为非法Key。那么当大量这样的请求过来时是不是都不会命中Redis,然后都会打到DB上,当DB瞬时接收到如此多的连接时,DB就有可能撑不住,挂掉。这就是存在的一个隐藏的漏洞,黑客或者恶意攻击者就会抓住这一点攻击你的系统,使你的系统瘫痪。

实际开发中就要考虑到这一点,可以在系统层面加一层过滤,将系统认为非法的key进行一次拦截,直接返回给客户端错误信息。具体这层过滤怎么加,哪些是非法Key要根据实际的业务逻辑来定,这里只给出解决思路

**缓存雪崩: **有很多个redis,设置了超时时间,在高并发情况下有大量的请求访问到redis,再从mysql数据库查询出的结果缓存到redis的这个过程中,恰好很多redis设置的超时时间过期了,那么会有大量的请求访问到这个redis,而在从mysql缓存到redis的这个过程中,由于很多redis的key已经失效,导致redis压力过大照成缓存雪崩情况

这个问题的解决办法就是,让Key的失效时间分散开,可以在统一的失效时间上再加一个随机值,或者使用更高级的算法分散失效时间。

***热点缓存(缓存击穿)***:缓存雪崩的一种特殊情况。指的是只有一个key的过期的情况

当Key失效后,假如瞬间突然涌入大量的请求,来请求同一个Key,这些请求不会命中Redis,
都会请求到DB,导致数据库压力过大,甚至扛不住,挂掉。
这个问题的解决办法就是:

1、设置热点Key,自动检测热点Key,将热点Key的过期时间加大或者设置为永不过期,或者设置为逻辑上永不过期,具体设置方法待会说。

2、加互斥锁。当发现没有命中Redis,去查数据库的时候,在执行更新缓存的操作上加锁,谁拿到锁谁去更新,同时在拿到锁之后先从缓存再获取一次如果有就返回,没有就查库然后更新。(双重校验)