为什么用Nosql
大数据:一般的数据库不行了
Memcached(缓存) + mysql + 垂直拆分(读写分离 分库分表)
读写分离 一些服务器干读 一些写
一般来说 读比写多
所以使用缓存 主要解决读的问题
缓存的发展过程:优化数据结构和索引–》文件(IO)—》memcached(当时最热门的技术)
分库分表:+ 水平拆分 +集群
集群 一组主从结构的数据库
本质:数据库(读,写)
缓存解决了读的问题 写呢?
早起用的myisam引擎 表锁(查一个 锁一张表 十分影响效率 高并发就会有问题)
Innodb 行锁 只锁一行
慢慢的就开始使用分库分表来解决写的压力 比如把一个User表拆分 各部分去写
Mysql集群 很好的满足了早期需求
如今:三体说近三十年,技术爆炸,定位也是一种数据,音乐,热榜,放早期无法实现
因为数据量大 变化很快
图形数据库出现 JSON BSON二进制JSON数据库也有
MySQL 有的使用它存储大的文件 数据库表很大 效率就低了
如果有一种数据库专门来处理这种数据 mysql压力就会变小
如何处理这些问题呢
大数据io的压力下 表几乎无法更改
目前一个基本的互联网项目:
用户访问 会先访问企业防火墙 分配负载均衡 给用户选择适合的服务器 服务器去对接数据库 还有很多其他类型的数据库 比如缓存 流媒体服务器 短信服务器 图片服务器 文件服务器 群发服务器
为什么nosql?
用户的个人信息 比如社交网络 地理位置 用户自己产生的数据 爆发式增长
这个时候我们就要使用nosql数据库 可以很好的处理以上的情况
Nosql不是sql吗 是not only sql 不仅仅是sql 泛指非关系行数据库
什么事关系型数据库 表格 行 列 (POI)
随着web2.0互联网的诞生 传统的关系型数据库很难适应web2.0时代 尤其是超大规模的并发 暴露出来很多难以克服的问题 nosql在当今大数据环境下发展的十分迅速redis是发展最快的 必须掌握!
很多的数据类型 个人信息 社交网络 这种类型不需要一个固定的存储 不需要多余的操作就可以横向扩展 比如集群
Map<String,Object> 存万事万物 这就是nosql的表现 get set 用键值对存 读
Nosql特点 1.方便扩展 因为数据之间无关系 为什么面向接扣编程 为了解耦
2.大数据高性能 redis 一秒写八万次 读11万 nosql的缓存记录级 细粒度 性能会比较高
3.数据类型是多样性的 不需要事先设计数据库 随取随用 如果是数据量十分大的表 很难设计
传统RDBMS 和nosql
结构化组织
Sql
数据和关系都存在单独的表中 row column
操作数据 数据定义
严格的acid原则
Nosql:
不仅仅是数据
没有固定的查询语言
键值对存储方式 列存储 文档存储 图形数据库
最终一致性
Cap定理和base理论(异地多活!)初级架构师
高性能 高可用 高可扩(随时可以水平拆分)
了解 3v+3高
3v主要是描述问题的 海量 多样 实时
3高 对程序的要求
真正的在公司中的实践 nosql+RDBMS 一起使用才是最强的
技术没有高低之分 看你怎么用
阿里巴巴演进分析
技术 急不得 越是慢慢学才能越扎实
敏捷开发 极限编程
任何一家互联网公司都不可能只是让用户来用
大量的公司都在做相同的业务
竞品协议
随着这样的竞争 业务越来越完善 然后对于开发者要求越来越高
没有什么是加一层解决不了的
Nosql四大分类
Kv键值对:
文档型数据库:(bson 和json一样)
Mongdb 基于分布式文件存储的数据库 c++编写 主要用于处理大量的文档
Mongdb 是一个介于关系型数据库和非关系型的中间产品 是nosql中功能最丰富
最像关系型的
追求幸福 探索未知
Redis是什么 c语言 基于内存 可持久化的kv数据库
1.内存存储 持久化 内存中断点即失 所以说持久化很重要(rdb aof)
2.效率高 可用于高速缓存
3.发布订阅系统
4.地同信息分析
5.计时器 计数器
6…
特点
1.多样的数据类型
2.持久化
3.集群
4.事务
5…
学习中需要用到的东西
官网:redis.io
中文网 redis.cn
Windows 在github下载 停更很久了
Redis推荐在linux服务器上搭建 基于linux学习
Widows下安装
Linux下安装
默认端口 6379 set k v
Get k 得到 v
Linux安装 把gz放到opt 解压
安装gcc环境
用cli链接6379 keys * 查看所有的key
ps -ef查看所有服务和链接
如何关闭redis-server shutdown exit redis结束
单机多redis启动集群
Redis默认有16个数据库 database 16 默认使用第0个数据库
可以用select 切换默认数据库
Dbsize 查看数据库大小
Keys* 查看当前数据库所有的key
Flushall 清空全部 flushdb 清空当前库
为什么redis6379 粉丝 6379刚好是个女明星
Redis是单线程的 redis是很快的 官方表示 redis是基于内存操作的 cpu不是redis的性能瓶颈 redis的瓶颈是根据机器 的内存和网络带宽所决定的 既然可以使用单线程来实现 就是用单线程了 6.0多线程
为什么单线程还这么快 c语言写的
高性能的服务器不一定是多线程的 多线程不一定比单线程效率高
核心:redis是将所有的数据全部放在内存中的 所以说使用单线程去操作效率就是最高的 因为多线程会产生上下文切换 是个耗时的操作 对于内存系统来说 如果没有上下文切换 效率就是最高的
多次读写 都是在一个cpu上的 所以在内存情况下 就是最佳的方案
五大数据类型
Redis可以做数据可 可以做缓存 可以做消息中间件
支持String hash散列 list sets zset有序
Exists key 看key是否存在
Move name 1 移动key到1数据库
设置过期时间 expire name 10 10s后消失 key的v消失
单点登录 可以把一些东西存到redis中
Ttl key 查看当前key的剩余时间
判断key的类型type key 看key具体类型
String
Append命令 append key1 “hello” 追加 如果当前key不存在 相当于新set了
Strlen 获取字符串长度
I++ 自增操作 incr views 就会自增 i-- decr views
设置步长 incrby views 10 decrby 10
字符串范围 range getrange(开始,结束(为-1查看全部))
替换一个范围 setrange key 1 xx 指定位置替换为xx
Setex 存在 就set (set with expire) 设置过期时间
Setnx 不存在就set(set if not expire) 不存在设置(在分布式锁中会常常使用)
Mest k1 v1 k2 v2 k3 v3设置多组kv
Mget k1 k2 k3 获取多组v
Msetnx 不存在就设置 存在就失败 msetnx 原子性 要么都成功 要么都失败
对象
Set user:1{name:zhangsan,age:3} 设置user:1对象 值为一个json字符串
还可以怎么做 mset user:1:name zhangsan user:1:age 2
Mget user:1:name user:1:age
这里的key是个巧妙的设计 user代表对象user:{id}:{field}这样的设置是完全ok的
组合命令 先get再set 如果不存在 就设置值 存在 就获取当前值 更改为新值
Getset db redis 再次get就有了
Getset db mongodb 再次get变为mongodb
Jedis 数据结构是相同的
String使用场景 value除了是字符串 还可以是数字 比如计数器 统计多单位数量
Uid:xxxxxxxx:follow:0(incr) 粉丝数 对象缓存
List 可以重复的值
在dedis中 可以把list玩成栈 队列
所有的list命令都是用l开头的
Lpush list one
Lpush list two
Lpush list three
Lrange list 0 -1 查看所有值 结果倒着展示 这不就是栈吗
Lrange list 0 1获取具体的值
Rpush list right 插到尾部
移除 pop lpop rpop
Lpop list 把队列第一个值取了
Rpop 最后一个取了
通过下标获取list中的某一个值
Index lindex 获取list 的第一个值 lindex list 1
可以做个生产者消费者模型
Llen lsit 长度?
移除指定的值 取关 uid为固定值 数量也可以自定义
Lrem list 1 one
Lrem list 2 three 移除两个three
只保留某一部分的元素
Java 中有个trim 修剪的操作 比如去空格
List 截断 ltrim mylist 1 2 通过下标截取制定长度 list已经只剩下下标为1 2 的元素了
移除列表最后一个元素 并将该元素替换到另一个list中的第一个位置
Rpoplpush mylist ohter
Lset 将列表中指定下标的值替换成另一个值
lInsert list before “a” “other” 在原值左边插入
after
小结:它实际上是一个双头链表 Node 如果key不存在 创建新链表 存在就新添内容
如果移除了key 所有value都没了 移除了所有值 也没了 在两边插入或者改动值 效率最高 中间元素 效率会偏低 实现消息排队吧 消息队列 lpush 从左边放入 rpop从右边出来队列 lpush lpop 这就是栈了
Set 集合 不可重复
开头都是s
Sadd myset hello
获取
查看全部 smembers
Sismember 是否存在某个元素?
Scard set 查看有多少元素 获取set中的个数
Srem set “hello” 移除hello
无序不重复集合 所以做一个抽奖系统
抽随机
Srandmember set 从set随机筛选一个
随即删除呢?谁是倒霉蛋
Spop set随机移除
将一个指定的值移动到另外一个set中
Smove myset myset2 “hello”
微博 b站 共同关注? 这是交集
数字集合类 差集 交集 并集
搞两个集合有不同 有相同
Sdiff set1 set2 找两个集合的差集 对方还关注了
Sinter set1 set2 找交集 你们都关注了
Sunion set1 set2 找并集 你们关注的所有人
任何人你都可以认识 只要去认识六个人 六度分割理论
Hash map集合
前面是 k v 现在变成k <k ,v> 和string没有太大区别 还是一个简单集合
只不过value变成了kv
这时候这个值是一个map
Set hash field bai
H开头
Hset myhash field1 bai k(myhahs):<k(field1),v(bai)>
Hget myhahs field1
Hmset myhash field1 hello field2 world set多个kv
Hmget myhash field1 field2 get多个kv
Hgetall myhash 获取所有的kv
删除一个指定的k字段 对应的value值也没了
Hdel myhash field1
获取所有的长度
Hlen myhash 一个键值对 就是1
判断某一个k中的k是否存在
Hexists myhash field1
只获得所有的k的k
Hkeys myhash
只获得所有k的k的v
Hvals myhash
自增1 自减同理
Hincrby myhash field3 1
不存在 自动创建 存在 创建不成功
Hsetnx myhash field4 hello
应用:可以存一些变更数据 user :name age 比如用户信息的保存 经常变动的信息
Hash更适合对象的存储 而STring更适合字符串
Zset 有序集合 底层 跳跃链表
Set的基础上 增加了一个值 set k1 v1 zset k1 score1 v1
Zadd myset 1 one
Zadd myset 2 two 要加标志 用来排序
Zrange myset 0 - 1 获取所有的值
排序如何实现
Zadd salary 2500 xiaohong
Zadd salary 5000 zhangsan
Zadd salary 500 xiaobai
根据薪水排序
Zrangebyscore salary -inf +inf 范围 正无穷到负无穷 由小到大排出来了
Zrangebyscore salary -inf +inf withscores 带成绩
Zrangescore salary -inf 2500 withscores 最低工资到2500 降序排列
由大到小
Zrevrange salary 0 -1
移除元素
Zrem salary xiaobai
查看有多少元素
Zcard salary
计算区间有多少个值
Zcount salary 1 3
应用 set排序 存储班级成绩 工资表排序 普通消息 重要消息 带权重进行判断 热搜榜
特殊数据类型
Geospatial 定位
朋友的定位 附近的人 打车距离计算
城市经度纬度查询
Redis的geo在3.2就有了 这个功能可以推算地理位置的信息 两地之间的距离
只有6个命令
Geoadd geodist geohash geopos georadius georadiusbymember
Geoadd
添加地理位置 经度 纬度 名称 规则 地球两极无法添加 一般会下载数据 直接java导入
参数 k 值(经度 纬度 名称)
Geoadd china:city 116.40 39.90 beijing
Geoadd china:city 121.47 31.23 shanghai
Geoadd china:city 106.50 29.53 chongqing
Geoadd china:city 114.05 22.52 shenzhen
Geoadd china:city 120.16 30.24 hangzhou
Geoadd china:city 108.96 34.26 xi’an
经度大纬度小
Geopos
Geopos china:city beijing
Geopos china:city beijing chongqing 获取指定的城市经纬度
geodist
返回两人之间的距离
单位参数M km mi ft 米千米英里英尺
Geodist china:city beijing shanghai km km为单位
找附近的人? 获得所有附近的人的地址 开定位
通过半径来查询 圆形搜索
Georadius 以给定的经纬度为中心 找出某一半径内的元素
Georadius china:city 110 30 1000 km 模拟自己的位置找方圆1000公里的城市
Georadius china:city 110 30 1000 km withdist 加上到那里的直线距离
获得制定数量的人 1000个人都显示吗 不 带显示经纬度
Georadius china:city 110 30 1000 km withdist withcoord count 1 只查一个
以北京为中心查方圆1000km的城市
Georadiusbymember china:city beijing 1000km
Geohash 返回一个或者多个位置 用hash表示 将二维经纬度转换为一维字符串
返回11个字符的geohash 一个hash字符串 两个hash越像 距离越近
Geohash china:city beijing chongqing
原理:底层的实现远离就是zset 有序集合 可以使用zset命令来操作geo
Zrange china:city 0 -1 查看地图中全部的元素
Zrem china:city beijing 就可以删除
Hperloglog 基数统计
什么是基数
a{1,3,5,7,8,7}
b{1,3,5,7,8}
不重复的元素b的基数 = 5
Redis 2.8.9就有hperloglog数据结构了
Redis hyperloglog 基数统计算法
统计一个网站uv(一个人访问一个网站 多次 但是还是算作一个人)页面访问量
传统的方式 set保存用户的id 不允许重复的 id一样就被覆盖了 然后就可以统计set中的元素数量 作为标准判断
上述方式如果保存大量的用户id就会比较麻烦 占内存 目的并不是保存用户id 是为了计数
而hyperloglog优点:占内存 十分小 是固定的 2^64不同元素的基数 只需要费12kb的内存
如果要从内存角度来比较的话 hperloglog就应该是uv的首选
有0.81%错误率 统计nv的话 可以忽略不计的
Pfadd mykey a b c d e f g h i j 放进去
Pfcount mykey 找到不重复的 基数
Pfadd mykey2 i j z x c v b n m
Pfcount mykey2 找基数
合并mykey 和 mykey2
Pfmerge mykey3 mykey mykey2 合并mykey 和 mykey2 生成mykey3
Pfcount mykey3结果为15 合并成功
了解:布隆过滤器
如果允许容错 那么一定可以使用hyperloglog 不允许就用set或者自己的数据类型
BItmaps 位运算
位存储 0 1 0 1
疫情 0 0 0 0 0 0 0存十四亿个0 感染了 记个1
快速求差值
统计用户信息 用户:活跃 不活跃 登录的 未登录的 打卡的 没打卡的
Userid status day 很麻烦
两个状态的都可以使用 bitmaps 位图一种数据结构 都是操作二进制位进行记录的
0 1两个状态 365天就是365bit
测试:
Setbit sign 0 0 第一个值为0
Setbit sign 1 1
…
七天 打卡模拟
查看某一天是否有打卡
Getbit sign 3 看周四打卡了没
统计操作 统计打卡的天数
Bitcount sign
以上三种特殊的数据结构 都有十分多的应用场景 多一个思路 技多不压身
事务
事务本质:一组命令的集合 一个事务中的所有命令都会在执行中序列化 顺序执行
执行特性:一次性 顺序性 排他性 执行系列的命令
一次性执行多个命令 序列化之后按顺序执行 执行时不允许加塞
Redis没有原子性 要么都成功 要么都失败
Redis事务没有隔离级别的概念
所以就可能出现脏读 幻读 重复读
所有的命令在事务中 并没有被直接执行 只有发起执行命令的时候才执行
Redis的事务
开启事务
命令入队
执行事务
有时候还用到锁 redis可以实现乐观锁 有个监视命令watch
开启事务:multi ok开启成功
中间写命令:
写完命令并没有直接执行 而是入队
执行: exec 直接把上面的命令全部执行
Ok此次事务执行完毕
其他情况 放弃事务 在执行之前 discard 取消了 所有写的都不执行
错误 编译异常 启动的时候报错 如果事务队列中 存在语法型错误 事务中所有的命令都不执行 因为编译就出错了
运行时异常 1/0 runtimeexception 比如让字符串自增 那么执行命令的时候 其他命令可以正常执行 这就是为什么没有原子性
总结就是 redis对事物是部分支持的 入队时报错 都不执行 运行时报错 正确的就执行了
观察redis锁的情况
Redis事务特点:单独的隔离操作 也就是一次性 顺序行 排他性
没有隔离级别概念: 因为事务提交前 里面的任何指令都不执行 所以像正常数据库的事务 要求在查询的时候要看到更新,事务外查询不允许查看这种情况了
非原子性:事务中一条命令执行失败 其他的还继续执行 不回滚
悲观锁 干啥都加锁 用完解锁
乐观锁 cas 认为不加锁 更新数据的时候去判断一下 在此期间 是否有人改动数据
Version字段mysql是这样
面试常问
Redis用watch 监视器 获取version 更新的时候比较version
一旦事务exec后 watch自动取消
也就是在事务执行之前 过来另一个线程修改了值 再执行事务 就会失败
失败了怎么解决 unwatch 然后再watch 每次watch就是获取最新的version
Jedis
使用java操作redis redis官方推荐的java链接开发工具 使用java操作redis中间件
知其然并知其所以
测试
先连接 再操作 最后断开
会用到Transaction类获取事务对象进行事务操作
利用fastJson的JSONObject类进行对象转换json字符串操作
ok连接成功
Redis和spring boot的整合
Springdata一个就够了 因为springdata整合了很多链接数据库工具
从boot 2.x之后 以前使用的jedis被替换成了 lettuce
区别呢?
Jedis 采用的是直连的方式 多个线程操作是不安全的 避免不安全 就要使用jedis的 pool 连接池 更像bio模式
Lettuce 底层采用netty 异步请求 实例可以在多个线程中共享 不存在线程不安全的情况 可以减少线程数量 更像Nio模式 性能会更高些
第一个方法 默认的 设置 对象都是需要序列化的
两个范型都是object类型 使用都要强转 可以自定义redisTemplate 替换这个默认的
第二个方法 由于sTring 是最常使用的类型 所以单独提出来的一个bean
进行连接测试
值的序列化配置
默认的序列化方式是jdk的序列化 转译
如果解决乱码 就要自己配置一个
自定义RedisTemplate 配置类 实现自定义序列化方式 解决乱码
在企业中 不会用太原生的代码
Redis.conf详解
单位:有单位大小的声明
配置文件对大小写不敏感 redis关键字也是如此
包含 include 把其他的文件包含进来
网络 绑定了本机ip 127.0.0.1 受保护模式 默认开启
端口 6379 tcp的一些配置
通用配置 守护进程开启 后台就可以运行了
开启守护进程之后 就需要指定一个pid进程文件
日志级别 debug
Logfile 日志生成的文件位置名 为空就没有
默认的数据库数量 默认16个
是否显示logo always show logo
快照 做持久化会用到 在规定的时间内执行了多少次操作 会持久化到
文件 .rdb .aof文件
持久化规则 内存数据库 没有持久化 数据就没了
Save 900 1 900s 至少有一个key修改一次 就进行持久化操作
Save 300 10
持久化如果出错 是否还需要继续工作
Rdbcompression 是否压缩rdb文件 消耗cpu资源
Rdb错误校验
Rdb文件保存的目录
Replication 主从复制
谁是主机 谁是从机
安全
设置redis 密码 get requiredpass 默认为空的
自己在conf里配置
通过命令设置
Set requirepass “123456” 设置密码
再get 没有权限了 所有的命令都不让用了
登录auth 123456 ok可以看了
客户端限制
最大客户端数 默认1w
Redis配置最大内存容量 默认有的
内存达到上限的策略 内存满了! 类似线程池满了 进行四中拒绝策略
Redis有六中常见的方式
各种删除key
Append only模式 aof
默认是不开启的 默认是使用rdb方式持久化的 大部分情况下 rdb完全够用了
后面讲原理
Appendonly.aof aof的持久化文件
是否每次都同步 每秒执行一次? 可能会丢失这一秒的数据
还有一个是每次操作都同步 消耗性能
不同步 操作系统自己同步数据 速度最快
工作中一些小小的配置 可以让你脱颖而出
持久化 RDB
面试和工作 持久化都是重点
必须会
Rdb aof
断电即使 一定要有持久化操作
行话 快照 snapshot
Redis会单独创建一个子进程 fork 会先将数据写到一个rdb临时文件 写完后 替换原来的快照文件 生成正式的rdb文件 rdb缺点:最后一次宕机了 会持久化失败
rdb保存的文件是dump.rdb文件
Aof是appendonly.aop文件
默认rdb名字也在配置文件中的snapshot中配置的
自定义配置文件中的内容 save 60 5 60s内修改了5次key 就会进行rdb操作
Dump.rdb触发机制 save命令条件达到了 执行flushall 也会触发
退出redis 也会产生
如何通过dump.rdb文件恢复呢
只需要将rdb文件放到redis的启动目录下 redis启动的时候会自动检查rdb文件 回复其中的数据 linux上再usr/local/bin中 放上rdb即可
几乎redis默认的配置就够用了 有时候在生产环境 我们会将dump.rdb文件进行备份
Rdb优点和缺点 优点:适合大规模的数据恢复 对数据的完整性要求不高
缺点:需要一定的时间间隔进程操作 如果redis意外宕机 最后一次修改的数据就没有了
Fork进程的时候 会占用一定的内存空间
AOF append only file 将我们的所有命令都记录下来
历史文件 恢复的时候 就把这个文件全部再执行一遍
Fork的子进程 最后生成一个aof文件 保存的文件是appendonly.aof
默认是不开启的 手动开启 我们只需要将appendonly 改为yes就开启了
重启redis就可以生效了
aof文件手动更改 并删掉rdb redis无法启动 不过可以去修复这个aof文件
使用redis提供的修复工具 redis-check-aof --fix修复一下
如果文件正常了 redis就可以直接恢复了 被瞎改的kv就被修复删除了
Aof优点和缺点
优点:一种是全丢 一种是丢部分 aof就是丢部分
每一次修改都同步 让文件完整性更好 默认是每秒同步一次 可能会丢失1s的数据
从不同不是效率最高的
缺点: 相对于数据文件来说 aof远大于rdb 修复速度也慢
Aof运行效率也比rdb慢 默认的就是rdb
配置文件里有个重写的配置 当aof文件超过64mb的时候就新写一个aof 是通过fork一个新的进程去将来将文件进行重写 毕竟aof默认是文件的无限制追加 这个文件会越来越大 这里重写意思是让aof文件变得更小 降低占用空间
Rdb常常放在从机上面 aof很少使用
扩展:
Rdb默认 aof自己写
Aof太大 后台优化重写
只做缓存 不需要做持久化了
Redis发布订阅
线程之间的通信 会用到队列 一个是发送者 一个是订阅着 双方通过管道收取
发布订阅pubsub也是一种消息通讯模式 比如微信 微博 有关注系统的
消息队列 rabbitmq等比较专业
List也可以做 发布订阅也可以
第一 消息发送者 第二 频道(消息发送者发 消息订阅者收) 第三 消息订阅者
Subscribe bai 订阅了bai频道
再打开个cli 发送这个消息
Publish bai “hello”
订阅者就会收到
退订 unsubscribe
中间是个字典 用户是链表
使用场景 实时消息系统 实时聊天(频道当成聊天室 将信息回显给所有人即可)
订阅 关注系统 稍微复杂点的:我们就会使用消息中间件来做
Mq kahfka
Redis主从复制
一个master 多个slave slave遵守master的命令
主节点 从机
四台都是redis 数据的复制都是单向的 主机以写为主 从机以读为主
最低需要一主二从 为了高可用 至少三台服务器
结构上 单点容易宕机
容量上 单个太小 redis最大内存不应该超过20g
只要在公司中 主从复制是必须要使用的
因为在真实的项目中 不可能单机使用redis
一个主节点 可以有多个仆从 单一个从节点只能有一个主节点
环境配置
只配置从库 不用配置主库 redis默认自己就是个主库
Info replication 查看当前库的信息 可以看其角色 master or slave 下面是否有从机
给每个主机准备一个conf
默认三台都是主机 只要去配从机就可以了
认老大 一主(79)二从(80,81)
Slavedof 127.0.0.1 6379 认6379为老大了
如果两个都配置完了 就是有两个从机的
这是用的命令 是暂时的
永久怎么改 进配置文件改
主机可以设置值 从机不能 只能读 主机中的所有信息和数据都会自动被从机保存
从节点不然写 主机报错了 从机可以给你复制回来
把主机断掉 从机还是从机 从机还连着主机 但是没有写操作了 照样能读数据
主机这时候回来了 从机依旧可以读主机的新东西
如果是使用命令行配置的从机 从机重启后 会变成主机
只要变成从机 就立马从主机中获取值
全量复制 增量复制
Slave启动后 链接master 会发送一个sync同步命令
Master接到命令 启动后台存盘进程 把整个数据文件都发给slave 完成一次完全同步
全量复制 salve收到数据后 存档并加载到内存中
增量复制 master继续将新的所有数据发给slave 玩成同步
但是只要slave重连master 就要进行一次全量复制
这种情况
让从机认一个从机作为master
中间那个依旧是从节点
这个情况也可以用
但是上面两种方法都不会用
用哨兵
如果主节点挂了 能不能让选一个老大出来呢
哨兵没有出来之前 这个是手动完成的 谋权篡位
如果主机断开了连接 slaveof no one 让自己变成主机
如果这个时候老大好了 那就得重新链接
人工干预 费时费力 造成一段时间服务不可用
哨兵模式
哨兵通过发送命令 等待redis响应 从而监视整个redis实例
哨兵都有可能挂掉 所以 多哨兵 哨兵还要互相监督
哨兵看到一个服务器没反应 视其为主观下线 多个哨兵发现都联系不上了 那就开始投票选新老大 投票又一个哨兵发起 进行故障转移操作 切换成功后 发布订阅模式 让各个哨兵把自己监控的从机进行一个切换主机操作 这个过程就叫做客观下线
测试 状态 一主二从 而非层层链路
先Sentinel.conf配置文件 配置哨兵 配sentinel monitor [name] 127.0.0.1 6379 1 就监控主机了 后面的1 意思 主机挂了 slave投票让谁变成主机
Ok 配置好了 启动哨兵
Redis-sentinel/sentinel.conf 哨兵启动
把主机shutdowm了 看看info replication 自动选举 等一下下就选出来了
Failover 故障转移
看日志就知道谁是新主机了
这时候把主机重新连过来 变成光杆司令了
优缺点
优点:哨兵集群 基于主从复制 所有的主从配置优点 他全有
主从可以切换 故障可以转移 系统的可用写就会变好
哨兵模式是主从模式的升级 手动到自动更加健壮
缺点
Redis不好在线扩容 集群容量一旦上限 再扩容很麻烦
实现哨兵模式的配置其实很麻烦 里面有很多选择
Redis缓存穿透 雪崩
服务器的高可用问题
缓存有的 就在换村里查 没有就去数据库
一种数据结构 hash化所有东西
缓存穿透(查不到)
缓存击穿(量太大,缓存过期) 设置热点key永不过期 分布式锁
分布式锁:大量人访问热点消息 缓存被穿透了 加锁 到数据库 只保证只用一个线程去数据库其余的进行等待
雪崩 redis集体宕机 或者 一堆key集中过期
双十一 停掉一些服务 保证主要服务可用 退款业务不让退
Redis高可用 多放些集群 异地多活
限流降级 缓存失效后 通过加锁 队列 控制对数据库的写 比如某个key只允许一个线程查询和写 其他线程等待
数据预热 正式部署之前 先把可能的数据预先访问一遍 让这些数据先让在缓存中 设置不同的过期时间 让缓存失效的时间有规律
小结:
Nosql 四大分类 具体使用 安装 测试性能 命令使用 五大数据类型 三大特殊类型
事务 jedis bio springboot整合 lettuce基于nettynio 自定制redisconf 序列化
Redis配置文件内容 持久化 rdb aof 快照 发布订阅subscribe 主从复制 如何搭建集群
主从复制 手动 哨兵模式 自动 缓存穿透 击穿 雪崩