redis原理

基于内存的key-value数据库
单进程单线程,1秒10万次读写,适合小数据量的高性能操作和运算上。
5种数据结构,string,hash,list,set,zset
Rdb和aof持久化策略

单个value最大1G
当你的key很小而value很大时,使用VM内存.
当你的key很大时,拆分大key为多个小key

什么是缓存穿透?

一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。如果key对应的value是一定不存在的,并且对该key并发请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。

如何避免?
1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。
2:对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤。【感觉应该用的不多吧】

缓存雪崩

什么是缓存雪崩?
当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。
如何避免?
1:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
2:不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。
3:做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期(此点为补充)

分布式锁

setnx和get,getset三个方法
setnx成功,加锁成功
setnx失败,get锁的过期时间与当前时间比较,如果锁过期了,getset设置锁的新的过期时间,返回旧的过期时间。
如果两个过期时间相等,加锁成功
如果失败,150毫秒后重试,最多10秒还失败,就加锁失败

while (timeout >= 0) {
            String expireTime = System.currentTimeMillis() + expireMillis + "";
            //把锁的过期时间写入锁的值
             //原子方法,应该也是同步的
            boolean setnx = setnx(LOCK_KEY, expireTime);

            //拿到锁
            if (setnx) {
                locked = true;
                log.debug("redis加锁成功, {} = {}", LOCK_KEY, expireTime);
                return true;
            }

            //没拿到锁, 但是锁过期了
            String oldExpireTime = get(LOCK_KEY);
            if (oldExpireTime != null && Long.parseLong(oldExpireTime) < System.currentTimeMillis()) {
                //getSet是同步的, 多个线程串行
                //第一个线程getSet的结果和get的结果相同, 拿到锁
                String beforeExpireTime = getSet(LOCK_KEY, expireTime);
                if (beforeExpireTime != null && beforeExpireTime.equals(oldExpireTime)) {
                    locked = true;
                    log.debug("redis加锁成功, {} = {}", LOCK_KEY, expireTime);
                    return true;
                }
            }

            //随机时间, 防止多个线程同时抢锁
            try {
                Thread.sleep(sleepMillis);
            } catch (InterruptedException e) {
                log.error(e.getMessage(), e);
            }
            timeout -= sleepMillis;
        }

Redis持久化方案

Rdb方式

Redis默认的方式,redis通过快照来将数据持久化到磁盘中。

设置持久化快照的条件
在redis.conf中修改持久化快照的条件,如下:
900秒修改1次,则持久化
300秒修改10次,则持久化
60秒内修改10000次,则持久化

Rdb问题
一旦redis非法关闭,那么会丢失最后一次持久化之后的数据。

如果数据不重要,则不必要关心。
如果数据不能允许丢失,那么要使用aof方式。

Aof方式
Redis默认是不使用该方式持久化的。Aof方式的持久化,是操作一次redis数据库,则将操作的记录存储到aof持久化文件中。

开启aof方式的持久化方案
将redis.conf中的appendonly改为yes,即开启aof方式的持久化方案。
查找/aof
找到appendonly no
按I进入insert模式,修改为
appendonly yes
按esc,:wq保存

需要重启redis后,bin目录内多了appendonly.aof文件,文件大小是0
操作一次数据库后,就记录一次,appendonly.aof的文件就变大

总结
1、aof文件比rdb更新频率高,优先使用aof还原数据。
2、aof比rdb更安全也更大
3、rdb性能比aof好
4、如果两个都配了优先加载AOF

redis如何控制AOF大小

Redis的AOF机制有点类似于Mysql binlog

随着命令不断写入AOF,文件会越来越大,为了解决这个问题,redis引入了AOF重写机制压缩文件。文件能缩小的原因是:
1.旧文件中的无效命令不会保留,如del key1,sort。
2.多条合并成一条,如lplush list a,lplush list b转换为lplush a b,也可以合并重复项。

重写的好处:减少AOF日志尺寸,减少内存占用,加快数据库恢复时间。

AOF重写可以手动触发和自动触发:
1.手动触发可以调用bgrewriteaof。
2.根据如下两个参数自动触发。
redis.conf
#代表当前AOF文件空间和上次重写后AOF空间的比值。
auto-aof-rewrite-percentage 100
#AOP超过10m就开始收缩
auto-aof-rewrite-min-size 10mb

AOF缩减自身文件大小的时候,数据库来了新的操作怎么办?

由于AOF的重写是由Redis主线程之外一个子线程执行,是在AOF写入的时候,会重新建立一个AOF重写缓冲区,当用户对数据库进行操作时,会把用户的操作追加到AOF重写缓冲区和AOF缓冲区中,此时AOF文件写入操作会同时从AOF缓冲区和AOF重写缓冲区两个地方读入数据,这样就保证了用户的添加修改操作的不丢失。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值