- 什么是nosql:
NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。
- 为什么要用nosql
- 现在数据量大
- 访问量大
- 高并发
- nosql特点
- 方便扩展
- 大数据量高性能
- 数据类型是多样性的
- nosql的四大分类
- KV键值对:阿里、百度-》Redis+memecache
- 文档型数据库(bson格式和json格式)
- mongodb是基于分布式文件存储的数据库,C++编写,主要处理大量的文档
- conthdb
- 列存储数据库
- HBase
- 分布式文件系统
- 图关系数据库
- 四大类型对比:
- 什么是Redis
Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。
- Redis用途:内存存储、持久化,内存中是断电即失、所以说持久化很重要(rdb\aof)
- 安装Redis(端口:6379):
- window安装
- 下载Redis(官网下载)
- 解压
- 进入目录开启服务,运行redis-server.exe文件即可
- 使用客户端连接Redis(运行redis-client.exe)
- window安装
-
- linux安装:
- 下载Redis(官网下载)
- 复制到服务器(linux)
- 解压到opt文件夹中
- 进入目录
- 执行 yum install gcc-c++ (要联网)
- 执行 make(下载环境)
- 执行 make install(确认安装环境了)
- redis的默认安装路径 “usr/local/bin”
- 备份redis的配置文件,该文件在解压目录里(redis.conf)
- redis运行不是在后台运行,要修改redis.conf配置文件
- linux安装:
-
-
- 启动redis服务:进人“/usr/local/bin”,执行redis-server 配置文件的位置/redis.conf
- 连接:redis-cli -p 6379
- 关闭服务:shutdown
-
- redis-benchmark是一个压力测试工具
例:redis-benchmark [option] [option value]
- redis基础知识
- 默认有16个数据库,默认使用第0个
- select进行切换数据库
- keys 查看key
- flushdb 清除当前数据库
- flushall 清除全部数据库
- redis是单线程的,基于内存操作,把全部数据放在内存,所以快
- redis的五大数据类型
- redis-key
- set key value:设值
- get key:取值
- keys *:查看所有值
- exists key:判断某值是否存在
- move key:移除值
- expire key time:设置值的有效时间,单位是秒
- ttl key:查看key的过期时间
- type key:查看key的类型
- redis-key
-
- String类型-用途:计数器,统计数量
- append key value:追加字符串,字符串不存在就新建
- strlen key:获取字符串的长度
- incr key:自加1,用于浏览量之类的操作
- decr key:自减1
- incrby key 长度:步长自加
- decrby key 长度:步长自减
- getrange key begin end:截取可以从begin到end的字符串
- setrange key begin value:用value替换从begin开始的值
- setex key value:设置过期时间
- setnx key value:不存在在设置(分布式锁中常用)
- mset key value key value ..:一次设置多个key
- mget key key ..:一次取多个key
- msetnx key value key value ..:不存在在设置
- String类型-用途:计数器,统计数量
-
-
- getset key value:先获取在设值
-
-
- List类型-用途:当栈、队列、阻塞队列用,他实际是一个链表,从左右插入数据
- 所有命令都是l开头的
- lpush key value:设值,从左边插入
- lrange keybegin end:会倒序,相当于栈
- rpush key value:设置,从右边插入
- lpop key:从左边移除
- rpop key:从右边移除
- lindex key index:通过下标获取值
- llen key:查看长度
- lrem key count value:移除count个value
- ltrim key begin end:截取值
- rpoplpush source 目的:移除最后一个元素再移动到新的列表中
- lset key index value:存在替换值,不存在报错
- linsert key before|after pivot value:在特定的位置插入值
- List类型-用途:当栈、队列、阻塞队列用,他实际是一个链表,从左右插入数据
-
- set(集合):值不能重复(用途:共同关注【并集】、)
- sadd key value:设值
- smembers key:查看元素
- sismember key value:判断是否存在该值
- scard key:查看长度
- srem key value:移除值
- srandmember key 【count】:随机获取值[多个值]
- spop key:随机移除元素
- smove source destination member:将一个指定的值移动到另一个集合中
- sdiff key1 key2:他们的差集(他们不同的)
- sinter key1 key2:他们的交集,共同好友、推荐好友、共同爱好等功能
- sunion key1 key2:他们的并集
- set(集合):值不能重复(用途:共同关注【并集】、)
-
- Hash(哈希),map集合(key-value)、用途:变更数据、对象的存储
- hset key field value:设置
- hget key field:取值
- hmset key field vallue [field vallue]:同时设置多个值
- hget key fileld [field]:获取多个值
- hgetall key::获取全部值
- hdel key field [field]:删除指定的值
- hlen key:获取长度
- hexists key field:判断指定值是否存在
- hvals key:只获取field
- hicnrby key field number:自加number
- hsetnx key field value :如果存在不能设值
- Hash(哈希),map集合(key-value)、用途:变更数据、对象的存储
-
- zset(有序集合):set排序,存储班级成绩,工资表,排行榜
- zadd key 位置(数字) value:设值
- zrangbyscore key min max:排序
- zrem key name:删除
- zcard key:获取有序集合的个数
- zcount key begin end:获取期间的数量
- zset(有序集合):set排序,存储班级成绩,工资表,排行榜
- 三种特殊数据类型
- geospatial地理位置
- 两地之间的距离,只有6个命令
- geoadd key 经度 维度 成员:添加地理位置(两极无法添加)
- geopos key 成员[成员]:获取指定的成员
- geodist key 成员 成员 单位(m\km\mi\ft):两个成员的距离
- georedius key 经度 维度 半径 范围:查找该半径方位的key(附近的人)
- georandiusbymember key 成员 半径:找出该范围的成员
- geohash key 成员:找出该成员的位置
- hyperloglog
- 基数的统计算法
- PFadd key:添加
- PFcount key:统计数量
- PFMERGE newkey key1 key2:合并
- bitmaps位存储:
- 统计用户信息,活跃、不活跃、登录、未登录等
- setbit key 成员 状态(0/1):添加
- getbit key 成员:获取成员状态
- bitcount key:统计状态
- geospatial地理位置
- 事务
- 本质:一组命令的集合,一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行!一次性、顺序性、排他性
- redis事务没有隔离级别
- redis单条命令有原子性,事务不保证原子性
- redis的事务
- 开始事务(multi)
- 命令入队(。。。)
- 执行事务(exec)
- 放弃事务(discard)
- 编译型异常(代码有误,命令有误):命令不会执行
- 运行时异常(0/1):异常命令不执行,其他会执行
- ====
- 悲观锁
- 认为做什么都有问题,无论做什么都加锁
- 乐观锁
- 认为什么时候都不出问题,不加锁
- 获取version
- 更新的时候比较version
- redis测试检测:watch key当做乐观锁
- UNwatch:解锁
- jedis
- 使用java操作redis,jedis是java操作redis的中间件
-
使用
- 创建maven项目
- 导入依赖
-
-
- 编写代码
-
-
-
- jedis的操作事务
-
- springboot整合redis
- springData是和springboot起名的
- 在springboot2.x之后,jedis改成了lettuce
- jedis和lettuce的区别
- 采用的直连,多个操作的话,是不安全的,如果想要避免不安全,就要使用jedis pool连接池(BIO)
- 采用nettly,实例可以在多个线程中进行共享,实现线程安全(NIO模式)
- 测试
-
- 创建springboot项目
- 导入依赖
-
-
- 配置
-
-
-
-
- 测试代码:对象要序列化
-
-
自己编写temp,实现序列化
在真实开发中自己写工具类
- redis.conf解析
- 单位
-
- 对大小写不敏感
- 网络:
-
- 快照
-
- 安全
-
- 限制
- redis持久化
- RDB:RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。
触发机制:
配置:
Redis会将数据集的快照dump到dump.rdb文件中。此外,我们也可以通过配置文件来修改Redis服务器dump快照的频率,在打开6379.conf文件之后,我们搜索save,可以看到下面的配置信息:
save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。
save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,则dump内存快照。
save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照
机制图:
-
- AOF:AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。
配置:
在Redis的配置文件中存在三种同步方式,它们分别是:
appendfsync always #每次有数据修改发生时都会写入AOF文件。
appendfsync everysec #每秒钟同步一次,该策略为AOF的缺省策略。
appendfsync no #从不同步。高效但是数据不会被持久化。
机制图:
-
- 两种机制的优缺点
RDB存在哪些优势呢?
1). 一旦采用该方式,那么你的整个Redis数据库将只包含一个文件,这对于文件备份而言是非常完美的。比如,你可能打算每个小时归档一次最近24小时的数据,同时还要每天归档一次最近30天的数据。通过这样的备份策略,一旦系统出现灾难性故障,我们可以非常容易的进行恢复。
2). 对于灾难恢复而言,RDB是非常不错的选择。因为我们可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。
3). 性能最大化。对于Redis的服务进程而言,在开始持久化时,它唯一需要做的只是fork出子进程,之后再由子进程完成这些持久化的工作,这样就可以极大的避免服务进程执行IO操作了。
4). 相比于AOF机制,如果数据集很大,RDB的启动效率会更高。
RDB又存在哪些劣势呢?
1). 如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。
2). 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟。
AOF的优势有哪些呢?
1). 该机制可以带来更高的数据安全性,即数据持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中。可以预见,这种方式在效率上是最低的。至于无同步,无需多言,我想大家都能正确的理解它。
2). 由于该机制对日志文件的写入操作采用的是append模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容。然而如果我们本次操作只是写入了一半数据就出现了系统崩溃问题,不用担心,在Redis下一次启动之前,我们可以通过redis-check-aof工具来帮助我们解决数据一致性的问题。
3). 如果日志过大,Redis可以自动启用rewrite机制。即Redis以append模式不断的将修改数据写入到老的磁盘文件中,同时Redis还会创建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行rewrite切换时可以更好的保证数据安全性。
4). AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上,我们也可以通过该文件完成数据的重建。
AOF的劣势有哪些呢?
1). 对于相同数量的数据集而言,AOF文件通常要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
2). 根据同步策略的不同,AOF在运行效率上往往会慢于RDB。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB一样高效。
二者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。rdb这个就更有些 eventually consistent的意思了。
- redis发布订阅
-
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
-
Redis 客户端可以订阅任意数量的频道。
-
-
- 常用命令
-
- 使用场景
- 实时消息系统
- 实时聊天
- 订阅,关注系统
- 使用场景
- redis主从复值
- 主从复制,读写分离,减少服务器压力
- 概念:
在Redis客户端通过info replication可以查看与复制相关的状态,对于了解主从节点的当前状态,以及解决出现的问题都会有帮助。
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master/leader),后者称为从节点(slave/follower);数据的复制是单向的,只能由主节点到从节点。
默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
- 作用
- 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
- 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
- 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
- 高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
-
- 配置
假设有两台服务器,一台是Linux操作系统(局域网IP:192.168.1.4,master服务器),一台是Linux操作系统(局域网IP:192.168.1.5,slave服务器)
配置slave服务器很简单,只需要在配置文件(redis.conf)中加入如下配置
bind 192.168.1.5(从服务器,此处默认是127.0.0.1,请修改成本机的IP地址,要不然,客户端无法进行访问)
slaveof 192.168.1.4 6379 (映射到主服务器上)
如果是在一台机器上面配置主从关系,那么还需要修改从服务器的默认端口号,同样也在redis.conf中进行修改。
-
- 主可以写,其他只能读
- 主机死机,从机当主机的配置:(哨兵模式解决这种问题)
手动:修改配置文件:saveof no one
- 哨兵模式
- 概念:哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
- 作用:
-
通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
-
当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。
-
- 配置:
主机:
哨兵:
# 配置监听的主服务器,这里sentinel monitor代表监控,mymaster代表服务器的名称,可以自定义,192.168.11.128代表监控的主服务器,6379代表端口,2代表只有两个或两个以上的哨兵认为主服务器不可用的时候,才会进行failover操作。
- redis缓存穿透和雪崩
- 缓存穿透
缓存穿透的概念很简单,用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。
这里需要注意和缓存击穿的区别,缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
- 解决方案
- 布隆过滤器
布隆过滤器是一种数据结构,垃圾网站和正常网站加起来全世界据统计也有几十亿个。网警要过滤这些垃圾网站,总不能到数据库里面一个一个去比较吧,这就可以使用布隆过滤器。
那这个布隆过滤器是如何解决redis中的缓存穿透呢?很简单首先也是对所有可能查询的参数以hash形式存储,当用户想要查询的时候,使用布隆过滤器发现不在集合中,就直接丢弃,不再对持久层查询。
-
- 缓存空对象
当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源;
但是这种方法会存在两个问题:
1、如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键;即使对空值设置了过期时间,还是会存在缓2、存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响。
-
- 缓存雪崩
概念:缓存雪崩是指,缓存层出现了错误,不能正常工作了。于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。
-
- 解决方案
(1)redis高可用
这个思想的含义是,既然redis有可能挂掉,那我多增设几台redis,这样一台挂掉之后其他的还可以继续工作,其实就是搭建的集群。
(2)限流降级
这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
(3)数据预热
数据加热的含义就是在正式部署之前,我先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。
- 总结:多学习,多编程。