Redis知识相关

Redis基础知识总结

2020-02-25  本文已影响0人  天行者YANG

Redis是完全开源的,极高性能的NoSql的数据库;读的速度能达到110000次/s,写的速度能达到81000次/s

数据类型

数据类型 可存储值
STRING 字符串、整数或者浮点数
LIST 列表
SET 无序集合
HASH 包含键值对的无序散列表
ZSET 有序集合

为什么是单线程的

数据淘汰策略

持久化

1.RDB

按照一定的时间将内存的数据以快照的形式保存到硬盘中,对应产生的数据文件为dump.rdb;如果系统发生故障,将会丢失最后一次创建快照之后的数据。

默认开启
#   save <seconds> <changes>
save 900 1
save 300 10
save 60 10000
保存流程(BGSAVE)
redis-rdb-flow.png

需要注意的是:

2.AOF

如何开启
appendonly yes
appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
重写流程
redis-aof-flow.png

需要注意的是:

3.雪崩、穿透、击穿

雪崩

现象:缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩(由于原有缓存失效,新缓存未到期间);

解决方案:考虑用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上;还有一个解决方案,原有的失效时间基础上增加一个随机值;

穿透

现象:查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义;

解决方案:如果一个查询返回的数据为空,我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟;

击穿(热点Key)

现象:缓存在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮;

解决方案:对缓存查询加锁,如果KEY不存在,就加锁,然后查DB入缓存,然后解锁;其他进程如果发现有锁就等待,然后等解锁后返回数据或者进入DB查询;

4.分布式锁

public boolean lock(int dbIndex, String key, String requestId, int cacheSeconds) {
        long beginTime = System.currentTimeMillis();
        boolean isBroken = false;
        Jedis jedis = null;
        boolean result;
        try {
            jedis = getJedis();
            jedis.select(dbIndex);
            //NX: SET IF NOT EXIST,没有SET,有的话不操作
            //PX: EXPX,过期时间设置
            String value = jedis.set(key, requestId, "NX", "PX", cacheSeconds);
            result = LOCK_SUCCESS.equals(value);
        } catch (Exception e) {
            isBroken = true;
            throw new JedisException(e);
        } finally {
            release(jedis, isBroken);
            LoggerBuilder.writeTimeLog("jedis-lock", beginTime);
        }
        return result;
    }


public boolean releaseLock(int dbIndex, String lockKey, String requestId) {
        long beginTime = System.currentTimeMillis();
        boolean isBroken = false;
        Jedis jedis = null;
        boolean result;
        try {
            jedis = getJedis();
            jedis.select(dbIndex);
            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            Object value = jedis.eval(script, Collections.singletonList(lockKey),
                Collections.singletonList(requestId));
            result = RELEASE_SUCCESS.equals(value);
        } catch (Exception e) {
            isBroken = true;
            throw new JedisException(e);
        } finally {
            release(jedis, isBroken);
            LoggerBuilder.writeTimeLog("jedis-releaseLock", beginTime);
        }
        return result;
    }

5.Redis 常见性能问题和解决方案

6.部署方式

6.1 主从

主从复制原理

一般主从配置可以缓解请求压力,做读写分离,写服务器不开启持久化,从服务器开启,从服务器还负责读取的操作,而且从服务器可以是多个,可以有效缓解主服务器的压力;但是坏处在于,如果主服务器宕机,无法自动切换恢复;

6.2 哨兵

主要作用

工作方式

哨兵其实是对主从配置的补充,可以自动选举出新的主,提供服务,但是,如果单机redis数据量过大,这个部署就无法处理了,需要cluster模式进行分片

6.3 集群
上一篇下一篇

猜你喜欢

热点阅读