redis笔记

数据库的本质

本质:读、写
随着数据不断的增量其一直在围绕解决读、写问题。

什么是NoSQL

nosql=not only sql 泛指非关系型数据库
关系型数据库:表格、行、列
很多数据类型用户的个人信息,社交网络,地理位置。这些数据类型的存储不需要一个固定的格式。不需要多余的操作就可以横向扩展的。

NoSQL特点

  1. 方便扩展(数据之间没有关系,很好扩展)
  2. 大数据量高性能(Redis一秒写8万次,读取11万)
  3. 数据类型是多样型的(不需要事先设计数据库、随取随用)

大数据3V+ 3高

3V是问题的描述

  1. 海量(Volume)
  2. 多样(Variety)
  3. 实时(Velocity)

3高是对程序的要求

  1. 高并发
  2. 高可扩
  3. 高性能

NoSQL的四大分类

1. KV键值对
新浪:Redis
美团:Redis+Tair
2.文档型数据库(bson格式)
MongoDB: 是一个基于分布式文件存储的数据库,C++编写,主要用来处理大量的文档;是一个介于关系型数据库和非关系型中中间的产品;其是非关系型数据库中功能最丰富,最像关系型数据库的。
3. 列存储数据库

  • HBase
  • 分布式文件系统

4 . 图关系数据库

  • 他不是存图片,是存放关系。比如:朋友圈社交网络,广告推荐!
  • Neo4J,InfroGrid

四大分类对比

在这里插入图片描述

redis安装

  • windows 直接解压即用
  • linux 下载解压后
// 需要用到 c环境
yum install gcc-c++
// 编译
make 

注:出现 fatal error: jemalloc 错误
原因:上次的编译失败,有残留的文件,我们需要清理下,然后重新编译就可以了。
解决:make distclean && make

启动

服务端:redis-server [配置文件路径.config]
客户端:redis-cli

概述

Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

非关系型数据库(nosql–>not only sql),C语言编写、性能极高、读写10w/s的速度;

  • 持久化:内存的数据可序列化后写入硬盘中,在次启动时在从硬盘加载到内存中。二进制安全;

  • 方便扩展:数据之间没有关系,很好扩展;

  • 数据类型多样型(不需要设计数据库,随取随用)

  • 单线程
    redis是基于内存操作,CPU不是redis的瓶颈,内存和带宽才是其瓶颈。
    单线程比多线程快?
    多线程涉及cpu调度的上下文切换,redis单线程基于内存非cpu。

     默认有16个数据库-config文件中配置
     默认连接0数据库
     选择数据库
     select index    index-1-16
     eg:select 0  默认为0数据库
     dbsize: 数据库大小
     move key   databaseIndex 移动数据
     flushdb 清除当前数据库
     flushall 清除所有的数据库
    

redis-config:端口、ip、密码、内存、超时、持久化设置(对少秒内,执行几次更新操作,才会持久化)等相关的配置

	内存溢出:一、设置超时时间、设置内存大小
		     二、采用内存策略

服务端:
redis-server (默认端口6379–明星效应,作者偶像明星对应的名字在九宫格6379)
客户端: cmd 窗口下载客户端目录测试连通
redis-cli: redis-cli -h 服务器ip -p 端口

关闭:客户端:shutdown-正常关闭,redis会执行持久化
kill-杀死进程:非法关闭时,在还没达到持久化条件时被关闭,无法持久化保存数据

作用

  • 数据库
  • 缓存
  • 消息中间件

常用命令

  • sekect index 选择数据库

  • dbsize 查看数据库大小(数量)

  • flushdb 清空当前数据库

  • flushall 清空所有数据库

  • del key (空格,多个key)

  • dump key 序列化

  • exists key 是否存在

  • expire key sedonds 设置过期时间(秒)----------默认情况是是永久有效(-1)

  • pexpire key millions 设置过期时间(毫秒)

  • ttl key 返回key的剩余生存时间(秒)

  • pttl key 返回key的剩余生存时间(毫秒)

  • persist key 移除key的时效时间,将key永久有效

  • keys
    *查询所有
    ?匹配一个字符

  • rename name newName 对Key重命名

  • move key index :移动key到指定数据库

  • type key 返回数据类型

五种基本数据类型

1.String
2. list
3. set
4. hash
5. zset

String(字符串)

  1. 赋值:
    set key value --如果存在key 则会覆盖value无视类型
    setnx key value --如果存在key 则无法赋值
  2. 取值:
    get key
    getrange key start end —截取value
    getset key —先取值在赋值
  3. 删除:
    del key
  4. 修改value(拼接):
    append key " "
    注:如果不存在就为 set key value
  5. 长度:
    strlen name
  6. 自增序列:
    incr key 数值加1
    incrby key 数值----每次增加值
  7. 自减序列
    decr key 数值减1
    decrby key 数值----每次减少值
    hdey key value 删除字段
  8. 合并操作:
    setex(set with expire) ---------------------setex name 30 xsux111
    setnx(set if no exsist) -----------(分布式锁中经常使用)------------setnt name xusx1111
  9. 批量:
    mset ----------------mset k1 v1 k2 v2
    mget -----------------mget k1 k2
    mstetnx -------------mset k1 v1 k4 v4(原子性操作,要么一起成功,要么一起失败–k1已存在)
  10. getset
    不存在值设置值,存在值替换值。返回:get而不是set结果
  11. 截取
    getrange key start end
    getrange name 0 -1 (截取全部长度)

Hash:key-map (哈希)

所有命令h开头

  1. 赋值
    hset key filed value
    批量:hmset key filed value filed value…------插入多个field value
  2. 取值
    hget key filed
    批量:hmget key filed filed 查询指定的多个filed
  3. 删除:
    hdel key filed
    del key 直接删除key
  4. 自增序列:
    hincrby key filed 数值
  5. 存在
    hexists key filed
  6. 长度
    hlen key
  7. 获取key 下所有filed
    hkeys key
  8. 获取全部key下所有的key-value
    hgetall key

应用:数据结构适合存储javaBean

List:字符串列表

字符串列表,按照插入顺序排序,类似于LinkList 可以在头部、尾部插入数据(列表)
数据结构:队列、栈
在这里插入图片描述
都是l开头的命令

  1. 插入左侧:
    lpush key value1[value2] 左边插入
    lpush list1 k1
    lpush list1 k2
    lpush list2 k1

  2. 插入右侧
    rpush key value1[value2] 右边插入
    rpush list1 k4

  3. 列表长度
    llen key 获取列表长度

  4. 获取范围内元素
    lrange key start stop 获取范围内的元素
    0:第一个元素
    -1:最后一个元素
    -2:倒数第二个元素

  5. 移除元素左
    lpop key 从左侧移除第一个元素

  6. 移除元素左
    rpop key 从右侧移除第一个元素

  7. 通过索引查找元素
    lindex key index 通过索引获取列表的元素0

  8. 移除指定元素:count 个value
    lrem key count value 移除对应list中count 个value
    注:one one two three–>lrem list 2 one -->two three

  9. 截取
    ltrim key start top 只保留指定区间内的元素,其余都被删除。
    rtrim key start top

  10. 移除放入
    rpoplpush source desction 移除源list最后一个元素放入目标list左

  11. 设置指定索引的值(更新)
    前置条件:list必须是存在的,index也必须是有效存在的。不存在报错。

    lset key index value 设置索引指定元素的值

    blpop key 从左侧移除并获取第一个元素。列表没有元素会阻塞等待超时或者弹出元素。
    brpop key 从右侧移除并获取第一个元素。列表没有元素会阻塞等待超时或者弹出元素。

  12. 在指定位置前后插入数据

    linsert key before||after oldvalue newvalue 值指定元素的值前||后插入数据。

    任务队列:

    rpoplpush a1 a2 : a1最后的元素调到a2的右侧
    rpoplpush a1 a2 :循环列表。将最后的元素移动到最左侧

Set: 唯一、无序(集合)

类似java中hashTable------其低层使用了intset 和hashtable 数据结构
所有命令为s开头

  1. 添加
    sadd key menmber1[menmber2] 向集合中添加一个或多个数据

  2. 返回所有元素
    smembers key 返回集合中所有的元素

  3. 是否存在
    sismember key menmber 判断集合中是否存在

  4. 集合个数
    scard key

  5. 移除指定元素
    srem key member1 [menmber2] 移除集合中一个或多个成员

  6. 随机返回元素(抽奖)
    srandmember key [count] 返回集合中一个或多个随机数

  7. 随机移除元素
    spop key [count] 移除并返回集合中的一个或多个随机成员

  8. 移动元素到另外一个集合
    smove source destination member 移动集合中的元素到另一个集合中

  9. 差集
    sdiff key1 key2 -------- key1相对于key2的差集
    sdiffstore destination key1 key2 将返回的结果集存入destination

  10. 交集:
    sinter key1 key2
    sintetstore destination key1 key2 将返回的结果集存入destination

  11. 并集:
    sunion key1 key2
    sunionstore destination key1 key2 将返回的结果集存入destination

Zset(有序集合)

唯一、有序。每个元素都会关联一个double类型分数。集合通过标识数来排序。集合的成员是唯一的,但是标识数可以重复的
每一个value 前有一个分数标识

  1. 添加
    zadd key score member [score menmber] :向集合中添加一个或多个数据 ----每一个成员都有一个score 。排序按照socre的大小排序。
  2. 数量长度
    zcard key
  3. 获取元素(低到高范围内 0 -1---->是获取所有)
    zrange key start end
  4. 获取元素(高到低范围内)
    zrevrange key start end
  5. 获取元素(附带分数)
    zrevrange key start end withscores
  6. 获取分数范围元素(-inf->负无穷;+inf->正无穷)
    zrangebyscore key min max
  7. 获取分数范围元素(反转)
    zrevrangebyscore key min max
  8. 获取标识数范围内元素数量
    zcount key min max 分数内的成员数
  9. 删除元素
    zrem key member 删除元素
  10. 获取有序集合中指定成员的索引
    zrank key member
  11. 删除分数区间内的元素
    zremrangebyscore key min max
  12. 删除索引区间内的元素
    zremrangebyrank key start stop 移除排名区间内的成员 0:第一位

三大特殊数据类型

geospatial 地理位置
redis3.2以后才有的

  1. 添加位置
    geoadd key longitude latitude member [longitude latitude member]
    eg: geoadd city 116.40 39.9 beijing
  2. 获取位置
    geopos keyu member
    geopos city beijing
  3. 获取两者之间的距离
    geodis key member1 member2
    eg:geodis city beijing wlmq
  4. 以指定经纬度为中心,获取半径范围内距离的元素
    范围可以使用以下其中一个单位:
  • m 表示单位为米。
  • km 表示单位为千米。
  • mi 表示单位为英里。
  • ft 表示单位为英尺。
    georadius key lon lat radius m|km|mi|ft [withcoord]-经纬度 [withdist]-距离 [COUNT conunt]要查询数量 [ASC-近到远|DESC远到近]
    georadius city 116 39 1000 km [参数]
127.0.0.1:6379> georadius city 116 39 1000 km
1) "beijing"
2) "shanghai"
127.0.0.1:6379> georadius city 116 39 1000 km withcoord
1) 1) "beijing"
   2) 1) "116.39999896287918"
      2) "39.389998986084969"
2) 1) "shanghai"
   2) 1) "121.47000163793564"
      2) "31.229999039757836"
127.0.0.1:6379> GEORADIUS city 116  39 1000 km withdist
1) 1) "beijing"
   2) "55.4123"
2) 1) "shanghai"
   2) "996.7785"
127.0.0.1:6379> GEORADIUS city 116 39 1000 km withdist count 1 desc
1) 1) "shanghai"
   2) "996.7785"
  1. 以指定元素为中心,获取半径范围内距离的元素
    geo底层使用的是zset
  2. 查询所有元素 zrange key 0 -1
  3. 删除元素 zrem key member

Hyperloglog 基数

  1. 何为基数
    基数为集合中不重复元素的个数
    A={1,3,4,5,5,6}的基数为5
  2. 简介
    Redis 2.8.9版本更新了Hyperloglog数据结构
    Redis Hyperloglog基数统计的算法
    优点:占用的内存是固定的。2^64不同元素的技术,只需要12KB内存,如果从内存角度来比较Hyperloglog首选。
    网页的UV(一个人访问网站多次但是还是算作一个人)
    传统的方式,set保存用户的id,然后就可以统计set中元素数量作为标准判断!这个方式如果保存大量的用户id,就会比较麻烦!我们的目的是为了技术,而不是保存用户id;
    0.81的错误率,统计UV任务。可以忽略不计
  3. 设置集合
    pfadd key member
    127.0.0.1:6379> pfadd mykey a b c d e
    (integer) 1
  4. 获取集合数量
    fpcount key
    127.0.0.1:6379> pfcount mykey
    (integer) 5
    127.0.0.1:6379> pfadd mykey2 e f g k l
    (integer) 1
  5. 生成基数集合
    127.0.0.1:6379> PFMERGE mykey3 mykey mykey2
    OK
    127.0.0.1:6379> PFCOUNT mykey3
    (integer) 9
    127.0.0.1:6379>

Bitmaps

位存储
统计用户信息活跃不活跃;登录不登录,打卡未打卡。只要其为两种状态的都可用Bitmaps,
Bitmaps位图。数据结构都是操作二进制位来进行记录,就只有0 1两个状态

  1. 设置
    127.0.0.1:6379> setbit sign 0 1
    (integer) 1
    127.0.0.1:6379>
    127.0.0.1:6379> setbit sign 1 0
    (integer) 1
    127.0.0.1:6379> setbit sign 2 0
    (integer) 0
  2. 获取
    127.0.0.1:6379> getbit sign 0
    (integer) 1
    127.0.0.1:6379> getbit sign 1
    (integer) 0
  3. 统计为1的个数
    127.0.0.1:6379> bitcount sign
    (integer) 1
    127.0.0.1:6379>

事务

本质:一组指令的集合,其顺序去执行
Redis 单条 命令有原子性,但Redis事务不保证原子性。(其中命令编译异常(命令错误)会停止;运行异常在会继续执行)
一次性、顺序性、排他性!执行一系列命令。
事务阶段:

  • 开启事务(multi)
  • 命令入队(…)
  • 执行命令 (exec)
  • 放弃事务 (discard)
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k1 v11
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) OK
4) "v2"
127.0.0.1:6379>

监控 watch–乐观锁

悲观锁:认为什么时候都会出问题,无论做什么都加锁;
乐观锁:认为什么时候都不会出问题,所以不加锁。在更新时候你判断下,在次期间是否有人修改过数据,
watch 去监视可以当做redis的乐观锁去操作。

当watch 去监视key,然后开启事务但还未执行;,当另一个线程更新了key。watch 监视比较后发现变化,则当前事务执行失败。放弃监视(unwatch key),重新监视(watch key)。获取最新在变化后,在去执行事务。

整合

-----------------------------------------------------java结合------------------------------------------
jar:jedis jar
jedisPoolConfig:连接池配置类
jedisPool:连接池
Jedis resource = jedisPool.getResource(); 获得jedis
----------------------------------------------------spring整合----------------------------------------
jar:spring-data-redis、jedis

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">

</bean>
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">

	<property name="hostName" value="127.0.0.1"></property>
	<property name="port" value="6379"></property>
	<property name="poolConfig" ref="jedisPoolConfig"></property>	

</bean>

<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
	<property name="connectionFactory" ref="jedisConnectionFactory"></property>
</bean>

java redis中存入数据,会默认对其进行java序列化后存入。
更改存入数据的序列化

<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
		<property name="connectionFactory" ref="jedisConnectionFactory"></property>
		<property name="keySerializer">
			<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean>
		</property>
		<property name="valueSerializer">
			<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean>
		</property>
</bean>	

java:
String: ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
Hash: HashOperations<String, Object, Object> opsForHash = redisTemplate.opsForHash();
ListOperations<String, String> opsForList = redisTemplate.opsForList();
[]

----------------------------------------------------springboot整合----------------------------------------
见springboot

redis.config

  • 可包含其他文件
    在这里插入图片描述

  • 网络

    • bind 127.0.0.1 ip
    • port 端口
    • protected-mode yes 保护模式
  • 通用

    • daemonize yes 以守护进程方式运行(后台),默认no ,我们需自己开启为yes
    • pidfile /var/run/redis_6379.pid 如果以后台方式运行,就需要指定一个pid文件
    • loglevel notice 日志级别
    • logfile “” 日志文件的位置
    • database 16 数据库的数量,默认是16
    • always-show-logo yes 是否总显示logi
  • 快照rdb

    • 持久化,在规定时间内执行了多少此操作,则会持久化到文件 .rdb .aof

    save 900 1 900s内至少1个key发生修改就就持久化
    save 300 10 同上
    save 60 10000 同上

    • stop-writes-on-bgsave-error yes 持久化失败是否继续工作
    • rdbcompression yes 是否压缩rdb文件
    • rdbchecksum 保存rdb文件的时候,进行错误的检查校验
    • dbfilename dump.rdb rdb文件名
    • dir ./ rdb文件保存目录
  • 安全

    • requirepass ****** 连接密码
      在这里插入图片描述
    • 客户端
      • maxclients 10000 设置能连接上redis最大客户端的数量
      • maxmemory reddis 配置最大的内存容量
      • maxmemory-policy noeviction 内存到达上限后的处理策略
        1. volatile-lru:只对设置了过期时间的key进行LRU算法进行删除
        2. allkeys-lru : 对所有key执行LRU算法进行删除
        3. volatile-lfu:只对设置了过期时间的key进行LFU算法进行删除
        4. allkeys-lfu:对所有key执行LFU算法进行删除
        5. volatile-random:随机删除设置有过期时间的key
        6. allkeys-random:随机删除
        7. volatile-ttl : 删除即将过期的
        8. noeviction : 永不过期,返回错误
  • aof

    • appendoly no 默认不开启aof ,默认是使用rdb方式持久化。大部分情况下rdb完全够用
    • appendfilename “appendonly.aof” 持久化的文件名字
    • 同步
      1. appendfsync always 每次修改都会syns ,消耗性能
      2. appendfsync everysec 每秒执行一次syns,可能会丢失这1s的数据
      3. appendfsync no

持久化

如果只做缓存,服务器关闭即可停止,则关闭持久化

  • RDB
    在指定的时间间隔内将内存中的数据集体快照写入磁盘,也就是Snapshot快照 ,它恢复时将快照文件读入到内存中
    Redis会单独创建一个子进程来进行持久化,会先将数据写入到一个临时文件夹中,待持久化过程都结束了,再用这个临时的文件替换上次持久化的好的文件,整个过程中,主进程是不进行任何IO操作的。这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化时发生了宕机数据可能丢失。
    默认是RDB,几乎其默认配制就满足大多数需求

    • 触发机制
      1. save规则满足的情况下会触发rdb
      2. 执行flushall命令,也会触发
      3. 退出redis,也会产生
    • 如何恢复rdb文件
      1. 只需要将rdb文件放在redis启动目录即可,redis启动会自动检查rdb文件
      2. 查看恢复存在的位置
      在这里插入图片描述
    • 优点
      1. 适合大规模的数据恢复
      2. 对数据完整性要求不高
    • 缺点
      1. redis意外宕机,则最后一次修改数据就没有了
      2. fork进程的时候,会占用一定的操作空间
  • AOF
    将所有的命令记录下来,history ,恢复的时候把这些命令全部执行一遍即可。
    以日志的形式记录每个写操作,将Redis执行过的所有指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初就会读取该文件重新构建数据。换言之,redis重启的话就根据日志文件内容将写指令从前到后执行一次以完成数据恢复工作。

    • 优点
      1. 每一次修改都同步,文件的完整度会更好
      2. 若每秒同步一次,可能对丢失一秒的数据
      3. 从不同步,效率最高
    • 缺点
    1. 修复速度比rdb慢
    2. aof运行效率也比rdb慢
  • 修复 (rdb与aof文件错位后的修改)

  1. redis-check-aof --fix
  2. redis-check-dump --fix
    在这里插入图片描述

发布、订阅

  • 订阅者

  • 渠道

  • 发送者
    在这里插入图片描述
    命令:
    publish channel message 发布 —主动推送
    subscribe channel 订阅

    应用:消息推送。公众号模式
    在这里插入图片描述

主从复制

主从复制(读写分离):是指将Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master/leader),后者称为从节点(slave/follower);数据的复制是单向的,只能由主节点到从节点。Master以写为主,Slave以读为主;主要解决读的问题,从节点是大于主节点的。
在这里插入图片描述

主从复制作用

  1. 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式
  2. 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余
  3. 负载均衡:在主从复制的基础上,配合读写分离。可以由主节点提供写服务,从节点提供读服务,分担服务器负载
  4. 高可用基石:主从复制还是哨兵和集群能够实施的基础。
    数据淘汰策略:
    当内存不足时,redis会根据配置的缓存策略淘汰部分key ,当无淘汰策略时或没有找到合适的淘汰key时。

环境搭建

多个从机配置文件
  1. 端口
  2. pid
  3. log
  4. dump

启动多个节点:
./redis-server + 配置文件
客户端链接不同节点:
./redis-cli -p
默认情况下都是主节点
在这里插入图片描述

设置从机–命令方式设置

命令:slaveof -host -p
在这里插入图片描述
设置完成后查看主机信息
在这里插入图片描述

设置从机-config配置文件方式
# slaveof <masterip> <masterport>

有密码则设置:

masterauth <master-password>
谋朝篡位

当主节点断开不存在,则从节点可以设置自己为主节点,其他从节点需要手动连接到当主节点
命令:slaveof on one

测试-细节

主机可以写,从机只能读,主机所有的数据信息都会保存到从机

  • 从机只能读:
    在这里插入图片描述
  • 主机断开,从机仍然是一直链接到主机的,主机回来后,从机仍然保持正常工作
  • 从机断开,若从机非配置文件设置的从机则要变成了主机;从机恢复为从机后,仍然可以获取主机的数据

复制原理

Slave 启动成功后连接到Master后会发送一个sync命令同步
Master接到命令后,启动后台的存盘进程,同时收集所有接受到的用于修改数据集命令后,在后台进程执行完毕之后,master将传送整个数据文件到slave,并完成一次完全同步。
全量复制:slave服务在接收到数据库文件数据后,将其存盘并加载到内存中
增量复制:master继续将所有收集到的修改命令依次传给slave,完成同步
只要是重新连接master,一次完全同步将被自动执行

哨兵模式

谋朝篡位自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转为主库
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行多个Redis实例。
在这里插入图片描述

哨兵作用:

  • 通过发送命令,让Redis服务器返回监控其运行的状态,包括主服务器和从服务器
  • 当哨兵检测到master宕机,会自动slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件。让他们切换主机。

哨兵集群:

一个哨兵开一个进程去监控所有节点,如果当前这个哨兵挂了怎么办
在这里插入图片描述
假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主管的认为主服务器不可用,这个现象称为主管下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定的值时,那么哨兵直接会进行一次投票。投票的结果由一个哨兵发起,进行failover[故障转移]操作,切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器切换到主服务器,这个过程称为客观下线。

启动哨兵

sentinel.conf 哨兵配置文件
  • port 26379
  • sentinel monitor
<master-name> <ip> <redis-port> <quorum>
启动

./redis-sentinel 配置文件

测试

主节点关闭后,哨兵自动故障转移重新设置了主节点,前主节点重启后就变为了从节点
在这里插入图片描述

哨兵优缺点

  • 优点
  1. 哨兵集群,基于主从复制模式,所有的主从配置有点,它全有
  2. 主从可以切换,故障可以转移,系统的可用性会更好
  3. 哨兵模式就是主从模式的升级版,手动到自动,更加健壮
  • 缺点
  1. Redis 不好在线扩容,集群容量一旦达到上线,扩容十分麻烦
  2. 实现哨兵模式配置麻烦

cluster

简介

  • redis3.0以后加入Cluster集群,实现了Redis分布式存储,也就是说每台机器都存储不同的内容。
  • redis集群采用P2P模式,是完全去中心化,不存在中心节点或者代理节点。
  • redis集群是没有统一入口的,客户端连接集群的时候连接集群中的任意节点。集群内部的节点是相互通信(PING-PONG),每个节点都是一个redis实例。
  • 为了实现集群的高可用,即判断节点是否正式使用,redis-cluster有这么一个投票容错机制:如果集群这种超过半数的节点投票认为某个节点挂了,那么这个节点就挂了。
  • 官方推荐最少配置3主3从

原理

slot(哈希槽)

集群内置了16384个slot,并把它们平均非配个各个主节点。当redis集群存放一个数据(key-value)时,redis会先对key进行crc16算法,将得到的结果对16384进行求余,这个余数对应[0-16384]其中一个槽,进而决定key-value存那个节点;一旦其中一个主节点挂了,并且没有相应的从节点来接管它的职责,那么该主节点所负责的哈希槽将变得不可用。
在这里插入图片描述

环境搭建(伪集群–三主三从)

6份redis
在redis目录下新建data文件夹

redis.conf通用配置
# 通用设置
bind地址修改:注释掉bind行或指定绑定的地址
port 7000
daemonize yes
pidfile /var/run/redis_7000.pid
dir /home/redis_cluster/data

# 集群相关
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

启动服务

在这里插入图片描述

创建集群
windows
redis版本一定要大于3.0,原因:windows暂不支持redis-cli创建集群,只能使用redis-trib.rb,redis-trib.rb是redis官方推出的管理redis集群的工具,需要redis版本>=3.0.6
linux
./redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 --cluster-replicas 1  [-a 密码]

cluster-replicas :一个主节点后面有几个从节点
在这里插入图片描述

验证

cluster nodes
在这里插入图片描述

过程中出现的问题
  1. 问题:集群启动后,有重新修改了ip后启动节点报错
    错误:
    [ERR] Node xxx is not empty. Either the node already knows other no…
    解决:
    1 删除每个redis节点的备份文件,数据库文件和集群配置文件
    比如说我有7001~7006 6个节点,那么每个节点中的appendonly.aof、dump.rdb、node_xxx.conf文件都要被删除
    2 使用redis-cli -c -h -p登录每个redis节点,使用以下命令
flushdb
cluster reset

3 重启所有的redis服务,再试试redis集群连接命令,应该就没问题了

./redis-cli --cluster create 192.168.79.128:7001 192.168.79.128:7002 192.168.79.128:7003 192.168.79.128:7004 192.168.79.128:7005 192.168.79.128:7006 --cluster-replicas 1
  1. 问题:telnet 无法平通虚拟机地址 ip
    解决:关闭虚拟机防火墙 systemctl stop firewalld
  2. 问题:redis/src下无redis-server
    解决: redis目录执行make
  3. 问题:no route to host 防火墙端口未开
sudo firewall-cmd --list-ports   查看防火墙打开所有的端口
firewall-cmd --zone=public --add-port=6379/tcp --permanent   开启端口
firewall-cmd --zone=public --remove-port=6379/tcp --permanent   关闭端口
firewall-cmd --reload   重新加载
  1. 显示:Waiting for the cluster to join 的字样,然后就无休无尽的等待…在这里插入图片描述
    遇到这种情况大部分是因为集群总线的端口没有开放!

每个Redis集群中的节点都需要打开两个TCP连接。一个连接用于正常的给Client提供服务,比如6379,还有一个额外的端口(通过在这个端口号上加10000)作为数据端口,例如:redis的端口为6379,那么另外一个需要开通的端口是:6379 + 10000, 即需要开启 16379。16379端口用于集群总线,这是一个用二进制协议的点对点通信信道。这个集群总线(Cluster bus)用于节点的失败侦测、配置更新、故障转移授权,等等。

解决: 只需要将开启Redis端口对应的 集群总线端口打开即可。例如: 6379 + 10000 = 16379。‘
防火墙打开集群节点+1000的端口

缓存穿透和雪崩(面试高频)

缓存穿透

缓存穿透的概念很简单,用户想要查询一个数据,发现Reds内存库中没有,也就是缓存没有命中,于是向持久层数据库查询,发现也没有,于是本次查询失败,当用户很多的时候,缓存都没有命中,就是持续查数据库就会给数据库造成很大的压力,这时候就相当于出现了缓存穿透。
在这里插入图片描述

解决方案(未完成)

布隆过滤器
缓存设置空对象

缓存击穿

这里需要注意和缓存击穿的区别,缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对一个点进行访问,这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在屏障上凿开一个洞。

解决方案

设置热点永不过期

从缓存层面来看,没有设置过期时间,不会出现key过期所产生的问题

加互斥锁

分布式锁:使用分布式锁,保证对于每一个key同时只有一个线程去查询后端服务,其他线程没有获得分布式事务锁的权限,只需等待。

缓存雪崩

是指某一个时间段,缓存集中过期失效;Redis宕机

解决方案

redis 高可用

redis有可能挂掉,那就多增加几台

限流降级

缓存失效后,用过加锁或者队列来控制读数据库写缓存的线程数量

数据预热

就是在正式部署之前,我先把可能数据先访问一遍。这样部分可能大量访问的数据就会加载到缓存中,在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

Redis 三种模式

主从(单体架构项目)

  • 通过持久化功能,Redis保证即使在服务器重启的情况下也不会丢失数据,因为持久化会把内存中数据保存到硬盘上,重启会从硬盘上加载数据。但是由于数据是存储在一台服务器上的,如果这台服务器出现硬盘故障等问题,也会导致数据丢失。
  • 为了避免单点故障,通常的做法是将数据库 复制多个副本以部署在不同的服务器上,这样即使有一台服务器出现了故障,其他的服务器依然可以继续提供服务,。为此,Redis提供了复制功能,可以实现当一台数据库中的数据更新后,自动将更新的数据同步到其他数据库上。
  • 在复制的概念中,数据库分为两类,一类是主数据库,另一类是从数据库
  • 主数据库可以进行读写操作,当写操作导致数据变化时会自动将数据同步给从数据库
  • 从数据库一般是只读的,并接受主数据库同步过来的数据
  • 一个主数据库可以拥有多个从数据库,而另一个从数据库只能拥有一个主数据库
  • 主要实现读、写分离

哨兵(单体架构项目)

- 当主机服务器宕机后,需要手动把一台服务器切换为主服务器。费时费力造成一段时间内服务不可用
- 哨兵模式是主从模式的升级版。哨兵是一个独立进程运行。
- 主要解决主节点挂了后,在从节点自动选出一位主节点来继续运行,实现**主动故障转移**。

cluster (集群)

 - redis在3.0后加入了集群模式,实现了redis的分布式存储,也就是说每台redis节点上存储不同的内容
 - 其继承了主从的读、写分离和哨兵的故障转移的优点
 - 方便横向扩容
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值