Redis入门

概念

  1. 高性能的NOSQL系列的非关系数据库

    1. 缓存机制的数据库
  2. 数据之间没有关系

  3. 数据存在内存中

  4. 下载安装

  5. 命令操作

数据结构

redis存储的是键值对的方式

key是键值对 value有五种数据类型

img

String

字符串类型 string string

String类型是二进制安全的,意思是 redis 的 string 可以包含任何数据。如数字,字符串,jpg图片或者序列化的对象。

  1. 存储 set key value
  2. 获取 get key
  3. 删除 del key

实战场景

1.缓存: 经典使用场景,把常用信息,字符串,图片或者视频等信息放到redis中,redis作为缓存层,mysql做持久化层,降低mysql的读写压力。

2.计数器:redis是单线程模型,一个命令执行完才会执行下一个,同时数据可以一步落地到其他的数据源。

3.session:常见方案spring session + redis实现session共享

Hash:map

哈希类型 hash :map格式

是一个Mapmap,指值本身又是一种键值对结构,如 value={{field1,value1},......fieldN,valueN}}

  1. 存储 hset key field value

  2. 获取

    hget key field :获取指定的值

    hgetall key :获取所有值

  3. 删除 hdel key field

实战场景

1.缓存: 能直观,相比string更节省空间,的维护缓存信息,如用户信息,视频信息等。

List:linkedlist

列表 list: linkedlist

List 说白了就是链表(redis 使用双端链表实现的 List),是有序的,value可以重复,可以通过下标取出对应的value值,左右两边都能进行插入和删除数据。

  1. 添加
    1. lpush key value : 将元素将入列表左边
    2. rpush key value : 将元素加入列表右边
  2. 查询
    1. lrange key start end : 范围获取
  3. 删除
    1. lpop key :删除列表最左边的元素,并将元素返回
    2. rpop key :删除列表最右边的元素 ,并将元素返回

实战场景

1.timeline:例如微博的时间轴,有人发布微博,用lpush加入时间轴,展示新的列表信息。

Set

集合类型 set: 不允许重复元素

集合类型也是用来保存多个字符串的元素,但和列表不同的是集合中

1. 不允许有重复的元素,

2.集合中的元素是无序的,不能通过索引下标获取元素,

3.支持集合间的操作,可以取多个集合取交集、并集、差集。

  1. 存储 :sadd key vlaue
  2. 获取: smembers key: 获取set所有元素
  3. 删除 : srem key value: 删除set集合中某个元素

实战场景

1.标签(tag),给用户添加标签,或者用户给消息添加标签,这样有同一标签或者类似标签的可以给推荐关注的事或者关注的人。

2.点赞,或点踩,收藏等,可以放到set中实现

Sortedset:zset

有序集合sortedset :不允许重复元素,且元素有顺序按照给定的score 分数排序(就和一个班里的同学学号不能重复,但考试成绩可以相同)。

  1. 存储 :zadd key score value

  2. 获取 : zrange key start end

  3. 删除 : zren key value

  4. 通用命令

    1. keys * 查询所有键
    2. type key : 获取键对应的value类型
    3. del key:删除指定的key value

实战场景

1.排行榜:有序集合经典使用场景。例如小说视频等网站需要对用户上传的小说视频做排行榜,榜单可以按照用户关注数,更新时间,字数等打分,做排行。

持久化操作

  1. RDB:默认的方式,不需要配置,默认就是使用这种机制

    1. 在redis.Windows.conf文件中编辑

      1. save 900 1
        1. 十五分钟后如果有一个key更新就持久化
      2. save 300 10
        1. 5分钟后,如果有十个key更新就持久化
      3. save 60 10000
        1. 1分钟后如果有一万个key更新就持久化
    2. 启用配置需要重启redis服务器,在redis路径cmd启动

      redis.server.exe redis.windows.conf
      
  2. AOF:日志记录的方式,可以记录每条命令的操作,可以每一次命令操作后,持久化数据

    1. 编辑redis.windows.conf文件
      1. appendonly no (关闭aof) --> appendonly yes (开启aof)
        1. appendfsync everysec : 每隔一秒进行一次持久化
        2. appendfsync always : 每次操作都进行持久化
        3. appendfsync no :不进行持久化
  3. 使用java操作redis

优缺点

RDB操作用save持久化会造成redis阻塞,redis不能处理其他命令

RDB使用bgsave可以异步进行快照操作,同时可以响应客户端的请求,通过创建子进程fork,持久化通过子进程完成

RDB通过配置方式去保存快照数据

AOF通过命令方式,每当一条命令过来就保存在aof文件中

Jedis

  1. 导包

  2. 创建Jedis对象,传入参数("IP地址",端口号)默认是localhost 6379

  3. redis有的方法,jedis也有

  4. 方法

    1. jedis.setex(key,second ,value)存储知道过期时间的key value
  5. 使用JedisPool工具类

  6. /**
        * 加载配置文件,配置连接池的参数
        * 提供获取连接的方法
        */
       private static JedisPool jedisPool;
      
       //获取配置文件信息
       static {
           InputStream stream = JedisPoolUtil.class.getClassLoader().getResourceAsStream("jedis.properties");
           //创建properties的对象读取文件
           Properties pro = new Properties();
           try {
               pro.load(stream);
           } catch (IOException e) {
               e.printStackTrace();
           }
           //获取数据,设置到JedisPoolConfig中
           JedisPoolConfig Config = new JedisPoolConfig();
           Config.setMaxTotal(Integer.parseInt(pro.getProperty("maxTotal")));
           Config.setMaxTotal(Integer.parseInt(pro.getProperty("maxIdle")));
           //初始化JedisPool
           jedisPool = new JedisPool(Config, pro.getProperty("host"), Integer.parseInt(pro.getProperty("port")));
      
       }
      
       public static Jedis getJedis() {
      
           return jedisPool.getResource();
       }
    

注意

  1. 使用redis缓存一些不经常发生变化的数据.
    1. 数据库的数据一旦发生改变,则需要更新缓存
      1. 数据库的表的执行,增删改查的操作,需要及时更新redis缓存数据情况,再次存入

Redis高级

Redis的数据特征

删除策略

Redis是一种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过TTL指令获取其状态

  • xx:具有时效性的数据

  • -1 :永久有效的数据

  • -2 :已经过期的数据或被删除的数据或未定义的数据

定时删除

  • 创建一个定时器,当key设置有效过期时间.且过期时间到达时,定时器任务立即执行删除操作
  • 优点:节约内存,到时就删除,快速释放不必要的内存占用
  • 缺点:CPU压力大,无论CPU此刻负载多高,均占用CPU,会影响redis服务器响应的时间和指令的吞吐量
  • 总结:用处理器性能换存储空间(用空间换时间)

惰性删除

  • 数据过期不做处理,等待下一次访问数据时候删除
    • 访问数据之前(get name)会执行一个expireIfNeeded()判断数据是否过期
    • 过期就删除,返回不存在
    • 未过期就返回数据
  • 优点:节约CPU性能,发现必须删除的时候才删除
  • 缺点:占用内存空间大,内存压力很大,出现长期占用内存的数据
  • 总结:用存储空间换取处理器性能(用时间换空间)

定期删除

  • Redis启动服务器初始化时,读取配置server.hz的值,默认为10

  • 每秒钟执行server.hz次serverCron()-------->databasesCron()--------->activeExpireCycle()

  • **activeExpireCycle()**对每个expires[*]逐一进行检测,每次执行耗时:250ms/server.hz

  • 对某个expires[*]检测时,随机挑选W个key检测

  如果key超时,删除key

  如果一轮中删除的key的数量>W*25%,循环该过程

  如果一轮中删除的key的数量≤W*25%,检查下一个expires[*],0-15循环

  W取值=ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP属性值
  • 参数current_db用于记录activeExpireCycle() 进入哪个expires[*] 执行

  • 如果activeExpireCycle()执行时间到期,下次从current_db继续向下执行

总的来说:定期删除就是周期性轮询redis库中的时效性数据,采用随机抽取的策略,利用过期数据占比的方式控制删除频度

  • 特点1:CPU性能占用设置有峰值,检测频度可自定义设置
  • 特点2:内存压力不是很大,长期占用内存的冷数据会被持续清理
  • 总结:周期性抽查存储空间(随机抽查,重点抽查)

淘汰策略

影响数据淘汰的相关配置

  • 最大可使用内存 默认值是0 不限制

    maxmemory ?mb
    
  • 每次选取待删除的数据个数,采取随机获取数据的方式

    maxmemory-sample  count
    
  • 对数据进行删除的选择策略

    maxmemory-policy policy
    
Policy
  • 检测易失数据(可能会过期的数据集server.db[i].expires )
    • LRU:least recently used 最近最少使用的 长时间不用的
    • LFU:least frequently used 最近不常用的 一段时间之内访问时间最少的
      1. volatile-lru:挑选最近最少使用的数据淘汰
      2. volatile-lfu:挑选最近使用次数最少的数据淘汰
      3. volatile-ttl:挑选将要过期的数据淘汰
      4. volatile-random:任意选择数据淘汰
  • 检测全库数据(所有数据集server.db[i].dict )
    1. allkeys-lru:挑选最近最少使用的数据淘汰
    2. allkeys-lfu:挑选最近时间次数最少的数据淘汰
    3. allkeys-random:任意选择数据淘汰
  • 放弃数据驱逐
    1. no-enviction(驱逐):禁止驱逐数据(redis4.0中默认策略),会引发错误OOM(out of memory)

缓存问题

  1. 穿透

    访问某个redis中不存在的值达到穿透 redis的效果 压力直达服务器

  2. 雪崩

    某个时间点key大批量过期导致访问并发直接压在服务器上

  3. 击穿

    某个key不断的扛着并发 到了过期时间后 并发直接打在服务器上

集群方案

主从复制Replication

读写分离 一台主节点 几台从节点 通过 slaveof ip 地址 端口号连接redis数据库,主节点可读可写 从节点只能读不能写

通过修改redis配置文件中配置

slaveof no one 断开连接

shut down关闭服务器

工作流程(三个阶段)

建立连接

数据同步

全量复制/部分复制
  1. 发送指令psync2

  2. master执行bgsave保存数据

  3. 当slave和master建立socket连接之后创建命令缓存区

  4. 生成RDB文件,通过socket发送slave

  5. 接收RDB,清空数据,执行RDB文件恢复进程

  6. 发送命令告知RDB恢复已经完成

  7. 发送复制缓冲区信息

  8. 接收信息 执行bgrewriteaof,恢复数据

数据同步阶段slave说明
  1. 如果master数据量巨大,数据同步阶段应避开流量高峰期,避免造成master阻塞,影响业务正常执行

  2. 复制缓冲区大小设定不合理,会导致数据溢出。如进行全量复制周期太长,进行部分复制时发现数据已
    经存在丢失的情况,必须进行第二次全量复制,致使slave陷入死循环状态。

    repl-backlog-size ?mb
    
  3. master单机内存占用主机内存的比例不应过大,建议使用50%-70%的内存,留下30%-50%的内存用于执
    行bgsave命令和创建复制缓冲区

数据同步阶段slave说明
  1. 为避免slave进行全量复制、部分复制时服务器响应阻塞或数据不同步,建议关闭此期间的对外服务

    slave-serve-stale-data yes| no
    
  2. 数据同步阶段,master发送给slave信息可以理解master是slave的一个客户端,主动向slave发送
    命令

  3. 多个slave同时对master请求数据同步,master发送的RDB文件增多,会对带宽造成巨大冲击,如果
    master带宽不足,因此数据同步需要根据业务需求,适量错峰

  4. slave过多时,建议调整拓扑结构,由一主多从结构变为树状结构,中间的节点既是master,也是
    slave。注意使用树状结构时,由于层级深度,导致深度越高的slave与最顶层master间数据同步延迟
    较大,数据一致性变差,应谨慎选择

命令传播和复制缓冲区工作原理

  • master接受到的命令发送给slave进行同步
命令传播的出现断网现象
  • 网络闪断 忽略
  • 短时间网络中断 部分复制
    • 三个核心要素info server /info 查看
      • 服务器的运行id
      • 主服务器的复制积压缓冲区
      • 主从服务器的复制偏移量
  • 长时间网络中断 全量复制

主从复制配置方式

心跳机制

哨兵sentinel

  1. 高可用(HA)介绍

    高可用是分布式系统架构设计中必须考虑的因素,通过架构设计减少系统不能提供服务的时间,保证高可用通常遵循下面几点:

    1. 单点是系统高可用的最大敌人,应该尽量在系统设计的过程中尽量避免单点
    2. 通过架构设计而保障系统的高可用.其核心准则是:冗余
    3. 实现故障自动转移
  2. 哨兵sentinel介绍

    1. sentinel(哨兵)是用于监控redis集群中Master状态的工具,其本身也是一个独立运行的进程,是Redis 的高可用解决方案,sentinel哨兵模式已经被集成在redis2.4之后的版本中。

    2. sentinel可以监视一个或者多个redis master服务,以及这些master服务的所有从服务;当某个master服务下线时,自动将该master下的某个从服务升级为master服务替代已下线的master服务继续处理请求,并且其余从节点开始从新的主节点复制数据。

    3. 在redis安装完成后,会有一个redis-sentinel的文件,这就是启动senkinel的脚本文件,同时还有一个sentinel.conf文件,这个是sentinel的配置文件。

    4. 配置sentinel哨兵

      #外部可以访问
      bind 0.8.8.0
      #设置哨兵监听的主服务器信息,最后一个数字是投票哨兵的数量,一般是除以二向上取整
      sentinel monitor mymaster 127.8.8.1 6379 1
      #设置判断宕机时长,该设置是否进行主从切换
      sentinel down-after-milliseconds mymaster 1008e
      #奢姿故障切换最大时长
      sentinel failover-timeout mymaster 6e8ee
      #设置主从切换后,同时进行数据同步的slave数量
      sentinel parallel-syncs mymaster 1
      

哨兵的工作原理

监控

sentinel之间发布订阅互通信息,监控master和slave运行状态

通知

故障转移

主观下线

任意一台的sentinel监控到master下线后记录该master状态消息sdown

客观下线

一半以上的sentinel再次发送消息给master确认是否下线,下线后记录odown

cluster集群结构搭建

Cluster配置

是否启用cluster,加入cluster节点

cluster-enabled yes| no

cluster配置文件名,该文件属于自动生成,仅用于快速查找文件并查询文件内容

cluster-config-file filename

节点服务响应超时时间,用于判定该节点是否下线或切换为从节点

cluster-node-timeout milliseconds

master连接的slave最小数量

cluster-migration-barrier min_slave_number

Cluster命令

redis-cli命令

添加master到当前集群中,连接时可以指定任意现有节点地址与端口

redis-cli --cluster add-node new-master-host:new-master-port now-host:now-port

添加slave

redis-cli --cluster add-node new-slave-host:new-slave-port
master-host:master-port --cluster-slave --cluster-master-id masterid

删除节点,如果删除的节点是master,必须保障其中没有槽slot

redis-cli --cluster del-node del-slave-host:del-slave-port del-slave-id

重新分槽,分槽是从具有槽的master中划分一部分给其他master,过程中不创建新的槽

redis-cli --cluster reshard new-master-host:new-master:port --oluster-from src-master-idl,src-master-id2,src-master-idn --cluster-to target-master-id --cluster-slots slots
  • 将需要参与分槽的所有masterid不分先后顺序添加到参数中,使用,分隔
  • 指定目标得到的槽的数量,所有的槽将平均从每个来源的master处获取

重新分配槽,从具有槽的master中分配指定数量的槽到另一个master中,常用于清空指定master中的槽

redis-cli --cluster reshard src-master-host:src-master-port --cluster-from src-master-id --cluster-to target-master-id --cluster-slots slots --cluster-yes
上一篇 下一篇