Redis入门

1、Redis支持的数据类型

  • String
  • Hash
  • List
  • Set
  • zset

2、redis特性

2.1 可靠性
	Redis Sentinal着眼于高可用,在master宕机时会自动将slave
	升为master,继续提供服务。
	Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。
2.3 持久化

AOF做增量持久化。因为RDB会耗费较长时间

  • RDB原理
	fork和cow。fork是指redis通过创建子进程来进行RDB操作,
	cow指的是copy on write,子进程创建后,父子进程共享数据段,
	父进程继续提供读写服务,写脏的页面数据会逐渐和子进程分离开来。
2.4 redis如何实现延时队列?
	sortedSet 时间戳作为score 
	内容消息作为key使用zadd加入
	消费者使用zrangebyscore

3、Redis 性能优化

  • 缩短键值对的存储长度;

在 key 不变的情况下,value 值越大操作效率越慢,因为 Redis 对于同一种数据类型会使用不同的内部编码进行存储,比如字符串的内部编码就有三种:int(整数编码)、raw(优化内存分配的字符串编码)、embstr(动态字符串编码),这是因为 Redis 的作者是想通过不同编码实现效率和空间的平衡,然而数据量越大使用的内部编码就越复杂,而越是复杂的内部编码存储的性能就越低。

当键值对内容较大时,还会带来另外几个问题:

  • 内容越大需要的持久化时间就越长,需要挂起的时间越长,Redis 的性能就会越低;
  • 内容越大在网络上传输的内容就越多,需要的时间就越长,整体的运行速度就越低
    内容越大占用的内存就越多,就会更频繁的触发内存淘汰机制,从而给 Redis 带来了更多的运行负担。
  • 使用 lazy free(延迟删除)特性;

lazy free 特性是 Redis 4.0 新增的一个非常使用的功能,它可以理解为惰性删除或延迟删除。意思是在删除的时候提供异步延时释放键值的功能,把键值释放操作放在 BIO(Background I/O) 单独的子线程处理中,以减少删除删除对 Redis 主线程的阻塞,可以有效地避免删除 big key 时带来的性能和可用性问题。

  • 设置键值的过期时间;

对键值设置合理的过期时间,这样 Redis 会帮你自动清除过期的键值对,以节约对内存的占用,以避免键值过多的堆积,频繁的触发内存淘汰策略

  • 禁用长耗时的查询命令;
决定禁止使用 keys 命令;

避免一次查询所有的成员,要使用 scan 命令进行分批的,游标式的遍历;

通过机制严格控制 Hash、Set、Sorted Set 等结构的数据大小;
将排序、并集、交集等操作放在客户端执行,以减少 Redis 服务器运行压力;

删除 (del) 一个大数据的时候,可能会需要很长时间,所以建议用异步删除的方式 unlink,
它会启动一个新的线程来删除目标数据,而不阻塞 Redis 的主线程。
  • 使用 slowlog 优化耗时命令;
  • 使用Pipeline 批量操作数据;

Pipeline (管道技术) 是客户端提供的一种批处理技术,用于一次处理多个 Redis 命令,从而提高整个交互的性能。

publicclass PipelineExample {
   public static void main(String[] args) {
       Jedis jedis = new Jedis("127.0.0.1", 6379);
       // 记录执行开始时间
       long beginTime = System.currentTimeMillis();
       // 获取 Pipeline 对象
       Pipeline pipe = jedis.pipelined();
       // 设置多个 Redis 命令
       for (int i = 0; i < 100; i++) {
           pipe.set("key" + i, "val" + i);
           pipe.del("key"+i);
       }
       // 执行命令
       pipe.sync();
       // 记录执行结束时间
       long endTime = System.currentTimeMillis();
       System.out.println("执行耗时:" + (endTime - beginTime) + "毫秒");
   }
}
  • 避免大量数据同时失效;

Redis 过期键值删除使用的是贪心策略,它每秒会进行 10 次过期扫描,此配置可在 redis.conf 进行配置,默认值是 hz 10,Redis 会随机抽取 20 个值,删除这 20 个键中过期的键,如果过期 key 的比例超过 25% ,重复执行此流程,如下图所示:

在这里插入图片描述

需要预防大量的缓存在同一时刻一起过期,就简单的解决方案就是在过期时间的基础上添加一个指定范围的随机数。

  • 客户端使用优化;

尽量使用 Redis 连接池,而不是频繁创建销毁 Redis 连接,这样就可以减少网络传输次数和减少了非必要调用指令。

  • 限制 Redis 内存大小;
  • 使用物理机而非虚拟机安装Redis 服务;
  • 检查数据持久化策略;
在 Redis 4.0 之后,Redis 有 3 种持久化的方式:

1、RDB(Redis DataBase,快照方式)将某一个时刻的内存数据,以二进制的方式写入磁盘;
2、AOF(Append Only File,文件追加方式),记录所有的操作命令,并以文本的形式追加到
文件中;
3、混合持久化方式,Redis 4.0 之后新增的方式,混合持久化是结合了 RDB 和 AOF 的优点
,在写入的时候,先把当前的数据以 RDB 的形式写入文件的开头,再将后续的操作命令以 AOF
 的格式存入文件,这样既能保证 Redis 重启时的速度,又能减低数据丢失的风险。

RDB 和 AOF 持久化各有利弊,RDB 可能会导致一定时间内的数据丢失,而 AOF 由于文件较大
则会影响 Redis 的启动速度,为了能同时拥有 RDB 和 AOF 的优点,Redis 4.0 之后新增了
混合持久化的方式,因此我们在必须要进行持久化操作时,应该选择混合持久化的方式。
  • 禁用 THP 特性;
  • 使用分布式架构来增加读写速度。
    1、主从同步
    2、哨兵模式
    3、Redis Cluster 集群

1、使用主从同步功能我们可以把写入放到主库上执行,把读功能转移到从服务上,因此就可以在单位时间内处理更多的请求,从而提升的 Redis 整体的运行速度。
2、而哨兵模式是对于主从功能的升级,但当主节点奔溃之后,无需人工干预就能自动恢复 Redis 的正常使用。
3、Redis Cluster 是 Redis 3.0 正式推出的,Redis 集群是通过将数据库分散存储到多个节点上来平衡各个节点的负载压力。
Redis Cluster 采用虚拟哈希槽分区,所有的键根据哈希函数映射到 0 ~ 16383 整数槽内,计算公式:slot = CRC16(key) & 16383,每一个节点负责维护一部分槽以及槽所映射的键值数据。这样 Redis 就可以把读写压力从一台服务器,分散给多台服务器了,因此性能会有很大的提升。
.
在这三个功能中,我们只需要使用一个就行了,毫无疑问 Redis Cluster 应该是首选的实现方案,它可以把读写压力自动的分担给更多的服务器,并且拥有自动容灾的能力。

4、Redis 架构模式

4.1、主从复制

Redis 的复制(replication)功能允许用户根据一个 Redis 服务器来创建任意多个该服务器的复制品,其中被复制的服务器为主服务器(master),而通过复制创建出来的服务器复制品则为从服务器(slave)。
.
只要主从服务器之间的网络连接正常,主从服务器两者会具有相同的数据,主服务器就会一直将发生在自己身上的数据更新同步 给从服务器,从而一直保证主从服务器的数据相同。

特点:

  • master/slave 角色
  • master/slave 数据相同
  • 降低 master 读压力在转交从库

问题:

  • 无法保证高可用
  • 没有解决 master 写的压力
4.2、哨兵机制

Redis sentinel 是一个分布式系统中监控 redis 主从服务器,并在主服务器下线时自动进行故障转移。其中三个特性:
监控(Monitoring):Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
提醒(Notification):当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
自动故障迁移(Automatic failover):当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作。

特点:

  • 保证高可用
  • 监控各个节点
  • 自动故障迁移

缺点:

  • 主从模式,切换需要时间丢数据
  • 没有解决 master 写的压力

5、面试相关

5.1 Redis的并发竞争问题

Redis为单进程单线程模式,采用队列模式将并发访问变为串行访问。Redis本身没有锁的概念,Redis对于多个客户端连接并不存在竞争,但是在Jedis客户端对Redis进行并发访问时会发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题,这些问题均是由于客户端连接混乱造成。对此有2种解决方法:

  • 客户端角度,为保证每个客户端间正常有序与Redis进行通信,对连接进行池化,同时对客户端读写Redis操作采用内部锁synchronized。
  • 服务器角度,利用setnx实现锁。

注:对于第一种,需要应用程序自己处理资源的同步,可以使用的方法比较通俗,可以使用synchronized也可以使用lock;第二种需要用到Redis的setnx命令,但是需要注意一些问题。

5.2 使用Redis实现分布式锁

先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。
如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?
set指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的!

5.3 使用Redis做异步队列

一般使用list结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。

参考:

Redis 最详细总结

Redis单例、主从模式、sentinel以及集群的配置方式及优缺点对比

高可用Redis服务架构分析与搭建

Redis的内存淘汰策略

Redis 性能问题分析

Redis 单线程却能支撑高并发

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值