Redis基础知识总结

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

数据类型

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

为什么是单线程的

  • Redis是基于内存的操作,CPU不是Redis的瓶颈
  • 省去了很多上下文切换线程的时间,不用去考虑各种锁的问题
  • 多路I/O复用:使用了单线程来轮询描述符,减少了线程切换时上下文的切换和竞争
  • 能带来更好的可维护性,方便开发和调试

数据淘汰策略

  • volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰
  • volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰
  • volatile-random:从已设置过期时间的数据集中任意选择数据淘汰
  • allkeys-lru:从所有数据集中挑选最近最少使用的数据淘汰
  • allkeys-random:从所有数据集中任意选择数据进行淘汰
  • noeviction:禁止驱逐数据
    需要先设置最大内存maxmemory,然后如果内存不足,会触发我们选择的过期淘汰策略

持久化

1.RDB

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

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

需要注意的是:

  • RDB写入,每次都是全量,在数据量特别大时,服务器负载会比较高
  • RDB会在服务器宕机时,丢失几分钟的数据,主要是根据save策略来的

2.AOF

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

需要注意的是:

  • 重写是直接把当前内存的数据生成对应命令,不需要分析老的AOF文件;
  • 恢复数据时,会先判断有没有AOF,没有的话,在加载RDB,因为AOF文件相对完整;

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 常见性能问题和解决方案

  • Master 最好不要做任何持久化工作;
  • 某个 Slave 开启 AOF 备份数据,策略设置为每秒同步一次;
  • 几个可能导致 Redis 阻塞的原因
    1.API或数据结构使用不合理,发现慢查询:slowlog get {n},发现大对象:redis-cli -h{ip} -p{port} bigkeys
    2.CPU饱和,redis-cli -h{ip} -p{port} –stat
    3.持久化阻塞,fork阻塞,使用info stats命令获取lastest_fork_usec指标,表示redis最近一次fork操作耗时;统计中的aof_delayed_fsync指标
    4.内存交换,cat /proc/{process_id}/smaps | grep Swap,如果交换量都是0KB或者个别4KB,是正常现象
    5.网络
  • 提高缓存命中率
    1.keyspace_hits / (keyspace_hits + keyspace_misses) = 命中率
    2.缓存时间越长,命中率会越高。时效性要求越低,就越适合缓存
    3.缓存的容量有限,则容易引起缓存失效和被淘汰
    4.缓存的粒度越小,命中率会越高

6.部署方式

6.1 主从

主从复制原理

  • 从服务器连接主服务器,发送SYNC命令;
  • 主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令;
  • 主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
  • 从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
  • 主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
  • 从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;(从服务器初始化完成)
  • 主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令(从服务器初始化完成后的操作)

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

6.2 哨兵

主要作用

  • 监控主服务器和从服务器是否正常运行
  • 主服务器出现故障时自动将从服务器转换为主服务器
  • 也具备了主从的全部好处

工作方式

  • 每个Sentinel(哨兵)进程以每秒钟一次的频率向整个集群中的Master主服务器,Slave从服务器以及其他Sentinel(哨兵)进程发送一个 PING 命令。
  • 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel(哨兵)进程标记为主观下线(SDOWN)
  • 如果一个Master主服务器被标记为主观下线(SDOWN),则正在监视这个Master主服务器的所有 Sentinel(哨兵)进程要以每秒一次的频率确认Master主服务器的确进入了主观下线状态
  • 当有足够数量的 Sentinel(哨兵)进程(大于等于配置文件指定的值)在指定的时间范围内确认Master主服务器进入了主观下线状态(SDOWN), 则Master主服务器会被标记为客观下线(ODOWN)
  • 在一般情况下, 每个 Sentinel(哨兵)进程会以每 10 秒一次的频率向集群中的所有Master主服务器、Slave从服务器发送 INFO 命令。
  • 当Master主服务器被 Sentinel(哨兵)进程标记为客观下线(ODOWN)时,Sentinel(哨兵)进程向下线的 Master主服务器的所有 Slave从服务器发送 INFO 命令的频率会从 10 秒一次改为每秒一次。
  • 若没有足够数量的 Sentinel(哨兵)进程同意 Master主服务器下线, Master主服务器的客观下线状态就会被移除。若 Master主服务器重新向 Sentinel(哨兵)进程发送 PING 命令返回有效回复,Master主服务器的主观下线状态就会被移除。

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

6.3 集群
  • 多个redis节点网络互联,数据共享
  • 所有的节点都是一主一从(也可以是一主多从),其中从不提供服务,仅作为备用
  • 不支持同时处理多个key(如MSET/MGET)
  • 支持在线增加、删除节点
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342