Nosql概述
1.单机Msql时代
90年代,网站访问量一般不太大,单个数据库足够用,更多的是静态网页html,服务器没有太大的压力
瓶颈:
- 数据量如果太大,一个机器放不下
- 数据的索引(mysql使用B+Tree),一个机器内存放不下
- 访问量(读写混合),一个机器承受不了
发生三种情况之一,必须要晋级(分布式)
2.memcached(缓存)+mysql+垂直拆分
网站80%的情况都是在读,每一次都去用命令查询数据库就会十分的麻烦,所以为了减轻数据库的压力,我们可以采用缓存(当遇到相同的命令时,直接从缓存里面调用)
发展过程:优化数据结构和索引–>文件缓存(IO)(当数据量更大,小文件太多,IO能力不足)–>Memcached(缓存)
3.分库分表+水平拆分+MySQL集群
本质:数据库(读、写)
引擎:
早些年MyISAM:表锁(查一行就会把整个表锁起来),十分影响效率,高并发下就会出现严重的锁问题
转战Innodb:行锁
慢慢的就开始使用分库分表(用户,订单之类的,单分一个表)来解决写的压力,mysql在那个年代推出了表分区,但是没有多少公司使用
mysql的集群解决了大部分公司的需求
4.最近的年代(技术爆炸)
MySQL等关系型数据库不够用了,数据量很多,变化很快
MySQL如果使用它去存储一些比较大的文件,图片,效率就会非常低,如果有种数据库专门存储这些数据,MySQL的压力就会很小,
大数据的IO压力下,表几乎没法增删
5.目前一个基本的互联网项目
6.为什么要用Nosql
用户的个人信息,社交网络,地理位置,等等爆发式的增长
这时我们需要使用Nosql数据库,去处理以上的情况
7.什么是NoSQL
关系型数据库:表格,行,列
Nosql = Not Only SQL,泛指非关系型数据库,随着web2.0互联网的诞生,传统的关系型数据库很难对付web2.0时代,尤其是超大规模的高并发的社区,NoSQL在当今大数据环境下发展 的十分迅速,Redis是发展最快的。
很多的数据类型用户的个人信息,社交网络,地理位置。这些数据类型的存储不需要一个固定的格式,不需要多余的操作就可以横向扩展的Map<string,object>使用键值对来控制
8.NoSQL特点
解耦
1.方便扩展(数据之间没有关系,很好扩展)
2.大数据量高性能(Redis一秒写8万次,读取11万,NoSQL的缓存记录级,是一种细粒度的缓存,性能会比较高)
3.数据类型是多样性的(不需要事先设计数据库,随去随用,如果是数据量十分大的表,很多人就无法设计)
4.传统RDBMS和NoSQL
传统RDBMS
- 结构化组织
- SQL
- 数据和关系都存在单独的表中
- 操作,数据定义语言
- 严格的一致性
- 基础的事务
- …
NoSQL
- 不仅仅是数据
- 没有固定的查询语言
- 键值对存储,列存储,文档存储,图形数据库(社交关系)
- 最终一致性(中间可以有些误差)
- CAP定理和BASE(异地多活)
- 高性能,高可用,高可扩
9.了解:
大数据时代的3v:主要是描述问题的
- 海量Volume
- 多样Variety
- 实时Velocit
大数据的3高:主要是对程序的要求
- 高并发
- 高可扩(随时水平拆分,可以扩展机器数量)
- 高性能
NoSQL和RDBNMS一起使用才是最强的,albb的架构演进
10.NoSQL的四大类
1.kv键值对:
- 新浪:Redis
- 美团:Redis+Tair
- 阿里、百度:Redis+memecache
2.文档型数据库(bson格式和json一样):
- MongoDB(一般必须要掌握)
- MongoDB是一个基于分布式文件存储的数据库,C++编写,主要用来处理大量的问题
- MongoDb是一个介于关系型数据库和非关系型数据库中的中间产品,MongoDB是非关系型数据库中功能最丰富,最像关系型数据库的
- ConthDB(国外)
3.列存储数据库
- HBase
- 分布式文件系统
4.图关系数据库
- 不是存图片的,放的是关系,比如:社交网络
- Neo4j,infoGrid
5.四者关系对比:
Redis入门
Redis是什么
Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
免费和开源,是当下最热门的NoSQL技术之一,也被人们称之为结构化数据库
Redis能干嘛
- 内存存储,持久化(内存中是断电即失,所以说持久化很重要(rdb,aof))
- 效率高,用于高速缓存
- 发布订阅系统
- 地图信息分析
- 计时器,计数器(浏览量)
- 当作数据库,缓存,消息中间键
- …
特性
- 多样性的数据类型
- 持久化
- 集群
- 事务
学习中需要用到的东西
- 官网:https://redis.io
- 中文网:https://redis.cn
Redis配置详解:
window
ping 测试链接,返回pong,即链接成功
set key value(存数据)
get key(取值)
window使用简单,但是redis推荐使用linux
Linux
配置过程
- centos6.5
- redis-6.2.6.tar.gz
基本的环境
yum install gcc-c++
make(在目标文件里面执行)
make install
redis默认安装位置: /usr/local/bin
将redis配置文件复制一份,
cp /opt/redis…/redis.conf /usr/local/bin/gconfig
之后就使用这个配置文件进行启动
redis默认不是后台启动的,修改配置文件
启动redis服务
查看redis的进程是否开启
关闭redis服务
测试性能
redis-benchmask
第6点,目前已经变成了3
测试:100个并发连接:100000请求
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
paylocal(有效负载)
基础的知识
redis中只有网络请求模块和数据操作模块是单线程的。而其他的如持久化存储模块、集群支撑模块等是多线程的
redis默认有16个数据数据库
默认使用的是第0个
可以使用select进行切换数据库(select 3)
dbsize查看数据库的存储数据的大小
查看所有的key
原本就写一个key(name),其余四个刚刚测试生成的
清除当前数据库:flushdb
清空所有的数据库:flushall
为什么redis端口号是6379?粉丝效应(手机九键对应的名字)
mysql端口号是3306?作者女儿的名字
redis是单线程的
redis是很快的,官方表示,redis是基于内存操作的,cpu不是redis性能瓶颈,redis的瓶颈是根据机器的内存和网络带宽,既然可以使用单线程来实现,就使用单线程了
redis是c语言写的,官方提供的数据为100000+的QPS,完全不比同样是使用memecache差
redis为什么单线程还这么快
- 误区1:高性能的服务器一定是多线程的
- 误区2:多线程(cpu上下文切换,而且还有线程锁,浪费资源)一定比单线程效率高,cpu>内存>硬盘 速度
核心:redis是将所有的数据全部放在内存中的,所以说使用单线程去操作效率就是最高的,多线程(cpu上下文切换:耗时的操作),对于内存系统来说,如果没有上下文切换效率就是最高的,多次读写都是在一个cpu上的,在内存情况下,这个方案是最佳的。
redis-key
判断某个键是否存在:exists key
移动key到某个数据库 move name 1
设置过期时间expire key 时间(s)
用途:具有时间限制的,比如:cookie
查看数据类型 type key
如果遇到不会的命令,在官网上查找
五大数据类型:
String(字符串)
90%的java程序员使用redis只会使用一个string类型
1.追加
append key value(返回字符串总长度)(如果key不存在,就相当于set)
2.字符串长度
strlen key
3.浏览量
将value设置成数字就可以实现
- incr key (增加1)
- incrby key 数字 (增加设置的数字)
- decr key(减少1)
- decrby key 数字(减少设置的数字)
4.截取字符串长度
getrange key 起始下标 终点下标
(下标从0开始,终点下标如果是-1,则查询所有 的字符串,都是闭区间)
5.替换字符串
setrange key 下标 替换字符串
6.setex(set with expire) 设置过期时间
7.setnx(set if not exist) 不存在就设置(在分布式锁中会常常使用)
8.设置多个值mset k1 v1 k2 v2 k3 v3
9.取出多个值mget k1 v1 k2 v2 k3 v3
10.msetnx是原子性的操作:要么成功,要么失败
11.对象
set user:1 {name:zhangsan,age:2}
设置一个user:1对象,值为json字符来保存一个对象
这里的key是一个巧妙的设计,user:{id}:{field},这样的设计在redis中是可以的
12.getset,先get再set
string类似的使用场景:value除了是我们的字符串还可以是我们的数字
- 计数器
- 统计多单位的数量
- 粉丝数
- 对象缓存存储
List
基本的数据类型,列表
在redis里面,我们可以把list玩成,栈,队列,阻塞队列
所有的list命令都是用L开头的
1.添加元素
2.移除元素
3.通过下标获取值
4.获取列表的长度
5.移除list指定的值
6.trim修剪:list截断
7.rpoplpush移除list的最后一个元素,并将他移动到新列表
8.lset将列表中指定下标的值替换为另外一个值,更新操作
如果列表不存在,我们去更新就会报错
如果存在,更新当前下标的值
如果超出下标,也会报错
9.linsert 将某个具体的value插入到某个元素的前面或者后面
小结:
- 实际上是一个链表,before Node after,left,right都可以插入值
- 如果key不存在,创建新的链表
- 如果key存在,新增内容
- 如果移除了所有的值,空链表,也代表不存在
- 在两边插入或者改值,效率最高,中间元素,相对来说效率会低一点
- 消息队列(Lpush Rpop),栈(Lpush Lpop)
Set(集合)
set中的值都是不可以重复的
1.scard key获取集合中元素的个数
2.srem key value移除指定元素
3.set无序不重复集合,抽随机
srandmember key 随机抽选一个元素
srandmember key 2 随机抽选两个元素
4.spop随机删除元素
5.smove将一个指定的值,移动到另外一个set集合
6.数字集合类
Hash(哈希)
Map集合,key-map这时候这个值是一个map集合(map key:value)
本质和string类型没有太大 区别,还是一个简单的key-value
1.hdel删除元素
删除hash指定key字段,对应的value消失
2.获取hash表的字段数量
3.判断hash中指定字段是否存在
4.hkeys 获取所有 的field
5.hvals 获取所有的value
hash变更的数据 user name age,尤其是用户信息之类的,经常变动的信息,hash更适合于对象的存储,string更适合字符串存储(比string少一个冒号),也可以用
6.hmset
7.hincrby,hsetnx
Zset(有序集合)
1.在set的基础上,增加了一个值,set k1 v1,zset k1 score v1
三种特殊数据类型:
Geospatial地理位置
1.getadd添加地理位置
规则:两极无法直接添加,我们一般会下载城市数据,直接通过java程序一次性导入
参数 key 值(经度,维度,名称)
2.geopos
获取当前定位:一定是一个坐标值
3.geodist
两人之间的距离
单位:
- m表示单位为米
- km表示单位为千米
- mi表示单位为英里
- ft表示单位为英尺
4.georadius以给定的经纬度为中心,找出某一半径内的元素(地图中要有)
附近的人(获取所有附近的人的地址,定位)通过半径来查询
5.找出位于指定位置周围的其他元素
6.删除地理位置
Hyperloglog
A(1,3,5,7,8,7)
B(1,3,5,7,8)
基数(不重复的元素)=5,可以接受误差
简介
redis2.8.9版本更新了Hyperloglog数据结构
Redis Hyperloglog基数统计的算法
优点:
占用的内存是固定,2^64不同的元素的技术,只需要占用12KB内存,如果要从内存的角度来比较的话,Hyperloglog首选
网页的UV(一个人访问一个网站多次,但是还是算作一个人)
传统的方式,set保存用户的id,然后就可以统计set中的元素数量作为标准判断
这个方式如果保存大量用户id,就会比较麻烦,我们的目的是为了计数,而不是保存用户id
0.81%错误率,统计UV任务,可以忽略不计
使用
如果允许容错,那么一定可以使用Hyperloglog
如果不允许容错,就使用set或者其他的数据类型
Bitmaps
位存储
统计用户信息,活跃,不活跃,登录,不登录
两个状态的,都可以使用Bitmaps
Bitmaps位图,数据结构,都是操作二进制位来进行记录,就只有0和1两个状态
365天=365bit 1字节=8bit 46个字节左右
使用bitmaps来记录周一到周日的打卡
判断某一天是否打卡
统计打卡天数
Redis持久化:
Redis是内存数据库,如果不将内存中的数据库状态保存到磁盘中,那么一旦服务器进程退出,服务器中的数据库状态也会消失,所以Redis提供了持久化的功能
rdb是二进制文件,aof是文本形式的
RDB:
rdb保存的文件是dump.rdb(备份)都是在我们的配置文件中快照中进行配置的
设置save后会自动触发rdb,不设置则需要手动save
save命令会阻塞redis服务器进程,直到rdb文件创建完毕,在此期间服务器不能处理任何命令的请求
触发机制
1.save的规则满足的情况下,会自动触发rdb规则
2.执行flushdb命令,也会触发我们的 rdb规则
3.退出redis,也会产生rdb文件
备份就自动生成一个dump.rdb
如何恢复rdb文件
1.只需要将rdb文件放在我们redis启动目录就可以,redis启动的时候会检查dump.rdb,恢复其中的数据
2.查看需要存在的位置
如果在这个目录下存在dump.rdb文件,启动就会恢复其中的数据
优点:
- 适合大规模的数据恢复!dump.rdb
- 对数据的完整性要求不高
缺点:
- 需要一定的时间间隔进程操作,如果redis意外宕机,这个最后一次修改数据就没有了
- fork进程的时候,会占用一定的内存空间
AOF(Append Only File):
将我们的所有命令都记录下来,history,恢复的时候就把这个文件全部再执行一遍
以日志的形式来记录每个写操作,将Redis执行过的所有指令记录下来(读操作不记录),只追加文件但不可以改写文件,redis启动之初会读取该文件重构数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作
aof保存的是append only.aof文件
appendonly默认是不开启的,需要手动开启
,开启后就开启了aof
重启redis
如果aof文件有错误,这个时候redis是启动不了的,我们需要修复这个aof文件
redis给我们提供一个工具redis-check-aof
会把错误的丢掉
重写规则说明
aof默认就是文件的无限追加,文件会越来越大
aof重写是将旧文件里面的最后一次修改完的数据和后面的写入指令保存到新的文件里面
如果aof文件大于64mb,太大了,fork一个新的进程来将我们的文件进行重写
优点:
- 每一次修改都同步,文件的完整会更好
- 每秒同步一次,可能会丢失一秒的数据
- 从不同步,效率是最高的
缺点:
- 相对于数据文件来说,aof远远大于rdb(文件),修复速度也比rdb慢
- aof运行效率也要比rdb慢,所以我们redis默认的配置即使rdb持久化
Redis事务操作:
要么同时成功,要么同时失败-----原子性
redis单条命令是保证原子性的,但是事务不保证原子性。
Redis事务没有没有隔离级别的概念
所有的命令在事务中,并没有直接被执行,只有发起执行命令的时候才会执行!
Redis事务本质:一组命令的集合!一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行
一次性,顺序性,排他性!执行一些列的命令
--------队列 set set set 执行-------
redis事务:
- 开始事务(multi)
- 命令入队()
- 执行事务(exec)
执行事务
放弃事务
编译型异常(代码有问题,命令有错)事务中所有的命令都不会被执行
允许时异常(1/0),如果事务队列中存在语法性,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常
监控Watch
悲观锁
很悲观,认为什么时候都会出问题,无论做什么都会加锁
乐观锁
很乐观,认为什么时候都不会出问题,所以不会上锁,更新数据的时候判断一下,在此期间是否有人修改过这个数据,version
获取version
更新的时候比较version
Redis测监视测试
测试多线程改值,使用watch可以当作redis的乐观锁操作
只要事务执行,不管成功还是失败都会自动解锁
分布式锁??????
Redis实现订阅分布:
redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接受消息
Redis客户端可以订阅任意数量的频道
测试
订阅端
发送端
使用场景:
- 实时消息系统
- 实时聊天(频道当作聊天室,将信息回显给所有人)
- 订阅,关注系统
- 稍微复杂的场景使用消息中间件MQ()
Redis.conf详解:
启动的时候,就通过配置文件来启动
1.配置文件unit单位对大小写不敏感
包含
可以配置多个文件
网络
bind 127.0.0.1 -::1 绑定ip
protected-mode yes 是否受保护,默认开启
port 6379 端口设置
通用GENERAL
daemonize yes 以守护进程的方式允许,默认为no
pidfile /var/run/redis_6379.pid 如果以后台的方式运行,我们就需要指定一个pid文件
日志
# Specify the server verbosity level.
# This can be one of:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel notice
logfile "" 日志的文件位置名,如果为空,就是一个标准的输出
databases 16 数据库的数量
always-show-logo no 是否显示logo
快照SNAPSHOTTING
持久化,在规定的时间内,执行了多少次操作,则会持久化到文件.rdb.aof
redis 是内存数据库,如果没有持久化,那么数据就会断电即失
3600秒内,如果至少有一个key经行修改,我们就进行持久化操作
# save 3600 1
300秒内,如果至少有100个key经行修改,我们就进行持久化操作
# save 300 100
60秒内,如果至少有10000个key经行修改,我们就进行持久化操作
# save 60 10000
持久化失败后,是否停止写入,默认yes
stop-writes-on-bgsave-error yes
是否压缩rdb文件(持久化文件),需要消耗cpu资源
rdbcompression yes
保存rdb文件的时候,,进行错误的检查校验
rdbchecksum yes
rdb文件保存的目录
dir ./
REPLICATION复制
SECURITY 密码
客户端CLIENTS
maxclients 10000 设置最大客户端的数量
# maxmemory <bytes> 默认最大的内存(字节)
# maxmemory-policy noeviction
内存到达上限之后的处理策略
1、volatile-lru:只对设置了过期时间的key进行LRU(默认值)
2、allkeys-lru : 删除lru算法的key
3、volatile-random:随机删除即将过期key
4、allkeys-random:随机删除
5、volatile-ttl : 删除即将过期的
6、noeviction : 永不过期,返回错误
APPEND ONLY MODE aof配置
appendonly no 默认不开启aof模式,默认使用rdb方式持久化的,在大部分所有的情况下,rdb完全够用
appendfilename "appendonly.aof"持久化的文件的名字
# appendfsync always 每次修改都会sync,消耗性能
appendfsync everysec 每秒执行一次sync,可能丢失这1s的数据
# appendfsync no 不执行sync,这个时候操作系统自己同步数据,速度最快
Redis主从复制:
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(masterleader),后者称为从节点(slave/follower);数据的复制是单向的,只能由主节点到从节点。Master以写为主,Slave以读为主。
默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。庄从复制的作用主要包括:
1、数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
2、故障恢复∶当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
3、负载均衡︰在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
4、高可用基石︰除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
一般来说,要将Redis运用于工程项目中,只使用一台Redis是万万不能的,原因如下︰
1、从结构上,单个Redis服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大;
2、从容量上,单个Redis服务器内存容量有限,就算一台Redis服务器内存容量为256G,也不能将所有内存用作Redis存储内存,一般来说,单台Redis最大使用内存不应该超过20G。
复制3个配置文件,然后修改对应的信息
- 端口
- pid名字
- log文件名字
- dump.rdb名字
修改完毕之后,打开服务
一主二从
默认情况下,每台redis服务器都是主节点,我们一般情况下只用配置从机就好了
在主机中查看
真实的主从配置应该在配置文件中配置,这样的话是永久的,但是现在是用的命令,暂时的
细节
主机负责写(也可以读),从机负责读,主机中所有的 信息和数据,都会自动被从机保存
测试:主机断开连接,从机依旧连接到主机的,但是没有写操作,这个时候,主机如果回来了,从机依旧可以直接获取到主机写的信息
如果是使用命令行,来配置的主从,这个时候如果重启了,就会变回主机!只要变回从机,立马就会从主机中获取数据。
复制原理:
Slave启动成功连接到master后会发送一个sync同步命令
Master接到命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,并完成一次完全同步。
全量复制︰而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步但是只要是重新连接master,一次完全同步(全量复制)将被自动执行
但是只要是重新连接master,一次完全同步(全量复制)将被自动执行,我们的数据一定可以在从机中看到。
如果主机断开了连接,我们可以使用slave no one 让自己变成主机,其他的节点就可以手动连接到最新的这个主节点(手动)如果这个时候原先的主节点修复,那就重新连接(手动)
Redis哨兵模式:
能够监控主机是否故障,如果故障了根据投票数自动从库转换为主库
哨兵模式是一种特殊的模式,首先redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。原理是哨兵通过发送命令,等待redis服务器响应,从而监控运行的多个redis实例。
这里的哨兵有两个作用:
通过发送命令,让redis服务器返回监控其运行状态,包括服务器和从服务器
当哨兵检测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让他们切换主机
一个哨兵可能会出问题,我们使用多个哨兵进行监控,各个哨兵之间还会进行监控,这样就形成了多哨兵模式
假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover[故障转移]操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。
配置哨兵配置文件sentinel.conf
sentinel monitor 被监控的名称 host port 1
sentinel monitor myredis 127.0.0.1 6379 1
后面的数字1,代表主机挂了,slave投票选举主机
启动哨兵
如果master节点断开了,这个时候就会从从节点选举一个作为主节点,如果主机回来了,就会变成slave
优点:
- 哨兵集群,基于主从复制模式,所有的主从配置优点,都有
- 主从可以切换,故障可以转移,系统的可用性就会更好
- 哨兵模式就是主从模式的升级,手动到自动
缺点:
- Redis不好在线扩容,集群容量一旦到达上限,在线扩容就会十分麻烦
- 实现哨兵模式的配置其实是很麻烦的,里面有很多选择
哨兵模式的全部配置
Example sentinel.conf
哨兵sentinel实例运行的端口 默认26379
port 26379
哨兵sentinel的工作目录
dir /tmp
哨兵sentinel监控的redis主节点的 ip port
master-name 可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
quorum 配置多少个sentinel哨兵统一认为master主节点失联 那么这时客观上认为主节点失联了
sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 2
当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码
设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒
sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000
这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1
故障转移的超时时间 failover-timeout 可以用在以下这些方面:
#1. 同一个sentinel对同一个master两次failover之间的间隔时间。
#2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
#3.当想要取消一个正在进行的failover所需要的时间。
#4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了
默认三分钟
sentinel failover-timeout <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000
SCRIPTS EXECUTION
#配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。
#对于脚本的运行结果有以下规则:
#若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
#若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
#如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
#一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
#通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本,这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时,将传给脚本两个参数,一个是事件的类型,一个是事件的描述。如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。
#通知脚本
shell编程
sentinel notification-script <master-name> <script-path>
sentinel notification-script mymaster /var/redis/notify.sh
客户端重新配置主节点参数脚本
当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。
以下参数将会在调用脚本时传给脚本:
<master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
目前<state>总是“failover”,
<role>是“leader”或者“observer”中的一个。
参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的
这个脚本应该是通用的,能被多次调用,不是针对性的。
sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh # 一般都是由运维来配置!
缓存穿透及解决方案:(查不到)
布隆过滤器(一般采用这个方式)
方案2的设计思路是通过设置过滤规则, 在数据库查询之前将数据进行过滤, 如果发现数据不存在, 则不再进行数据库查询, 以此来减小数据库的访问压力
方案2中过滤规则目前主流的一种的载体就是布隆过滤器. 布隆过滤器是一种概率型数据结构,特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”.
相比于传统的 List、Set、Map 等数据结构,布隆过滤器是一个bit数组, 它更高效、占用空间更少,但是缺点是其返回的结果是概率性的,而不是确切的。
如果我们要映射一个值到布隆过滤器中,我们需要使用多个不同的哈希函数生成多个哈希值,并对每个生成的哈希值指向的 bit 位置 1,例如针对值 “zhangsan” 和三个不同的哈希函数分别生成了哈希值 1、4、7
我们现在再存一个值 “lisi”,如果哈希函数返回 4、5、8 的话,图继续变为:
当我们想要判断布隆过滤器是否记录了某个数据时,布隆过滤器会先对该数据进行同样的哈希处理, 比如 “wangwu”的哈希函数返回了 2、5、8三个值,结果我们发现 2 这个 bit 位上的值为 0,说明没有任何一个值映射到这个 bit 位上,因此我们可以很确定地说 “wangwu” 这个数据不存在。
但是同时我们会发现,4 这个 bit 位由于”zhangsan”和”lisi”的哈希函数都返回了这个 bit 位,因此它被覆盖了。那么随着布隆过滤器保存的数据不断增多, 重复的概率就会不断增大, 所以当我们过滤某个数据时, 如果发现其三个哈希值都在过滤器中进行了记录, 那么也只能说明过滤器中可能包含了该数据, 并不能绝对肯定, 因为可能是其他数据的哈希值对结果产生了影响.这也就解释了上文所说的 布隆过滤器只能说明“某样东西一定不存在或者可能存在”.至于为什么采用三种不同的哈希函数取值, 因为三个哈希值只要有一个不存在就说明数据一定不在过滤器中, 这样做是可以减小因哈希碰撞(两个数据的哈希值相同)产生的错误概率.
布隆过滤器在很多语言中都有封装的工具包, 下边以python的工具包 `pybloomfiltermmap3 为例演示一下代码
import pybloomfilter
创建过滤器(数据容量, 错误率, 存储文件) 错误率越低, 文件越大
filter = pybloomfilter.BloomFilter(1000000, 0.01, 'words.bloom')
添加数据
filter.update(('bj', 'sh', 'gz'))
判断是否包含
if 'bj' in filter:
print('包含')
else:
print('不包含')
缓存空对象
缓存击穿及解决方案:(流量太大,缓存过期)
设置热点数据永不过期
加互斥锁
static Lock reenLock = new ReentrantLock();
public List<String> getData04() throws InterruptedException {
List<String> result = new ArrayList<String>();
// 从缓存读取数据
result = getDataFromCache();
if (result.isEmpty()) {
if (reenLock.tryLock()) {
try {
System.out.println("我拿到锁了,从DB获取数据库后写入缓存");
// 从数据库查询数据
result = getDataFromDB();
// 将查询到的数据写入缓存
setDataToCache(result);
} finally {
reenLock.unlock();// 释放锁
}
} else {
result = getDataFromCache();// 先查一下缓存
if (result.isEmpty()) {
System.out.println("我没拿到锁,缓存也没数据,先小憩一下");
Thread.sleep(100);// 小憩一会儿
return getData04();// 重试
}
}
}
return result;
}
缓存雪崩及解决方案:
指某一个时间段,缓存集中过期失效,redis宕机
redis高可用(搭建集群)
限流降级
数据加热
基础API之jedis详解:
什么是Jedis是Redis官方推荐的java连接开发工具!使用java操作Redis中间件!如果使用java操作redis,那么一定要对Jedis十分熟悉!
1.导入对应的依赖
2.编码测试
- 连接数据库
- 操作命令
- 断开连接
SpringBoot集成Redis操作:
Redis的实践分析: