什么是NoSQL
NoSQL = Not Only SQL,意思:不仅仅是SQL;
泛指非关系型的数据库,随着互联网Web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别
是超大规模和高并发的社 交网络服务类型的Web2.0纯动态网站已经显得力不从心,暴露了很多难以克服
的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展,NoSQL数据库的产生就是为
了解决大规模数据集合多种数据种类带来的挑战,尤其是大数据应用难题,包括超大规模数据的存储。
Redis入门
1)Redis是什么
是完全开源免费的,用C语言编写的,遵守BSD协议,是一个高性能的(Key/Value)分布式内存数据
库,基于内存运行,并支持持久化的NoSQL数据库,是当前最热门的NoSQL数据库之一,也被人们称为
数据结构服务器
2)redis能干嘛
a)内存存储和持久化:redis支持异步将内存中的数据写到硬盘上,同时不影响继续服务
b)效率高,持久化,内存中是断电即失,所以持久化很重要
c)取最新N个数据的操作,如:可以将最新的10条评论的ID放在Redis的List集合里面
发布、订阅消息系统
地图信息分析
定时器、计数器
3)redis的特性
a)多样的数据类型
b)持久化
c)集群
d)事务
4)Redis为什么这么快?
a)以前一直有个误区,以为:高性能服务器 一定是多线程来实现的
原因很简单因为误区二导致的:多线程 一定比 单线程 效率高,其实不然!
在说这个事前希望大家都能对 CPU 、 内存 、 硬盘的速度都有了解了!
b)redis 核心就是 如果我的数据全都在内存里,我单线程的去操作 就是效率最高的,为什么呢,因为
多线程的本质就是 CPU 模拟出来多个线程的情况,这种模拟出来的情况就有一个代价,就是上下文的切
换,对于一个内存的系统来说,它没有上下文的切换就是效率最高的。redis 用 单个CPU 绑定一块内存
的数据,然后针对这块内存的数据进行多次读写的时候,都是在一个CPU上完成的,所以它是单线程处
理这个事。在内存的情况下,这个方案就是最佳方案。
因为一次CPU上下文的切换大概在 1500ns 左右。从内存中读取 1MB 的连续数据,耗时大约为 250us,
假设1MB的数据由多个线程读取了1000次,那么就有1000次时间上下文的切换,那么就有1500ns *
1000 = 1500us ,我单线程的读完1MB数据才250us ,你光时间上下文的切换就用了1500us了,我还不
算你每次读一点数据 的时间。
redis五大基本类型
可以用作数据库、缓存和消息中间件MQ
1)Redis键(key)
在这里插入图片描述
2)字符串String
a) 单值value
set、get、del、append、strlen
**incr、decr 一定要是数字才能进行加减,+1 和 -1。 # incrby、decrby 命令将 key 中储存的数字加上指定的增量值。
**
range [范围]
getrange 获取指定区间范围内的值,类似between…and的关系,从零到负一表示全部
setrange 设置指定区间范围内的值,格式是setrange key值 具体值
setex(set with expire)键秒值
setnx(set if not exist)
mset Mset 命令用于同时设置一个或多个 key-value 对。
mget Mget 命令返回所有(一个或多个)给定 key 的值。
如果给定的 key 里面,有某个 key 不存在,那么这个 key 返回特殊值 nil 。
msetnx 当所有 key 都成功设置,返回 1 。
如果所有给定 key 都设置失败(至少有一个 key 已经存在),那么返回 0 。原子操 作
设置对象
常规key-value缓存应用:
常规计数:微博数,粉丝数等
2)列表List
单值多Value
a)Lpush:将一个或多个值插入到列表头部。(左)
rpush:将一个或多个值插入到列表尾部。(右)
lrange:返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。 其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推。 # 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此 类推
b)lpop 命令用于移除并返回列表的第一个元素。当列表 key 不存在时,返回 nil 。
rpop 移除列表的最后一个元素,返回值为移除的元素。
c)Lindex,按照索引下标获得元素(-1代表最后一个,0代表是第一个)
d)llen 用于返回列表的长度。
e)lrem key 根据参数 COUNT 的值,移除列表中与参数 VALUE 相等的元素。
f) Ltrim key 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区 间之内的元素都将被删除。
g)rpoplpush 移除列表的最后一个元素,并将该元素添加到另一个列表并返回。
h) lset key index value 将列表 key 下标为 index 的元素的值设置为 value 。
i) linsert key before/after pivot value 用于在列表的元素前或者后插入元素。 将值 value 插入到列表 key 当中,位于值 pivot 之前或之后。
性能总结:
它是一个字符串链表,left,right 都可以插入添加
如果键不存在,创建新的链表
如果键已存在,新增内容
如果值全移除,对应的键也就消失了
链表的操作无论是头和尾效率都极高,但假如是对中间元素进行操作,效率就很惨淡了。
3)集合set
a)sadd 将一个或多个成员元素加入到集合中,不能重复
smembers 返回集合中的所有的成员。
sismember 命令判断成员元素是否是集合的成员。
b)scard,获取集合里面的元素个数,
srem key value 用于移除集合中的一个或多个成员元素
**c)srandmember key 命令用于返回集合中的一个随机元素。
**
d)spop key 用于移除集合中的指定 key 的一个或多个随机元素
e)smove SOURCE DESTINATION MEMBER
将指定成员 member 元素从 source 集合移动到 destination 集合。
**f)数字集合类
- 差集: sdiff
- 交集: sinter
- 并集: sunio**
4)哈希Hash
kv模式不变,但V是一个键值对
a)hset、hget 命令用于为哈希表中的字段赋值 。
hmset、hmget 同时将多个field-value对设置到哈希表中。会覆盖哈希表中已存在的字段。
hgetall 用于返回哈希表中,所有的字段和值。 # hdel 用于删除哈希表 key 中的一个或多个指定字段
b)hlen 获取哈希表中字段的数量。
hexists 查看哈希表的指定字段是否存在。
hkeys 获取哈希表中的所有域(field)。
#hvals 返回哈希表所有域(field)的值。
c)hincrby 为哈希表中的字段值加上指定增量值。
hsetnx 为哈希表中不存在的的字段赋值 。
5)有序集合Zset
a) zadd 将一个或多个成员元素及其分数值加入到有序集当中。 #zrange 返回有序集中,指定区间内的成员
b)zrangebyscore 返回有序集合中指定分数区间的成员列表。有序集成员按分数值递增(从小到大) 次序排列。
c)zrem 移除有序集中的一个或多个成员。
zcard 命令用于计算集合中元素的数量。
zcount 计算有序集合中指定分数区间的成员数量。
d)zrank 返回有序集中指定成员的排名。其中有序集成员按分数值递增(从小到大)顺序排列。
zrevrank 返回有序集中成员的排名。其中有序集成员按分数值递减(从大到小)排序。
三种特殊数据类型
1)GEO地理位置
a)geoadd
b)geopos
c)geodist
d)georadius
e)georadiusbymember
f)geohash
g)zrem
2)HyperLogLog
什么是基数?
比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。
基数估计就是在误差可接受的范围内,快速计算基数。
3)BitMap
BitMap 就是通过一个 bit 位来表示某个元素对应的值或者状态, 其中的 key 就是对应元素本身,实际上
底层也是通过对字符串的操作来实现。Redis 从 2.2 版本之后新增了setbit, getbit, bitcount 等几个
bitmap 相关命令。
a)setbit 设置操作
b)getbit 获取操作
c)bitcount 统计操作
事务
1)概念
Redis 事务的本质是一组命令的集合。事务支持一次执行多个命令,一个事务中所有命令都会被序列
化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事
务执行命令序列中。
2)Redis不保证原子性:
Redis中,单条命令是原子性执行的,但事务不保证原子性,且没有回滚。事务中任意命令执行失败,其余的命令仍会被执行。
3)Redis事务的三个阶段:
开始事务
命令入队
执行事务
4)Redis事务相关命令
watch key1 key2 … #监视一或多个key,如果在事务执行之前,被监视的key被其他命令改动,则 事务被打断 ( 类似乐观锁 ) multi # 标记一个事务块的开始( queued ) exec # 执行所有事务块的命令 ( 一旦执行exec后,之前加的监控锁都会被取消掉 ) discard # 取消事务,放弃事务块中的所有命令 unwatch # 取消watch对所有key的监控
5)watch监控
悲观锁:
悲观锁(Pessimistic Lock),顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在
拿数据的时候都会上锁,这样别人想拿到这个数据就会block直到它拿到锁。传统的关系型数据库里面就
用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在操作之前先上锁。
乐观锁:
乐观锁(Optimistic Lock),顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会
上锁。但是在更新的时候会判断一下再此期间别人有没有去更新这个数据,可以使用版本号等机制,乐
观锁适用于多读的应用类型,这样可以提高吞吐量,乐观锁策略:提交版本必须大于记录当前版本才能
执行更新。
说明:
一但执行 EXEC 开启事务的执行后,无论事务使用执行成功, WARCH 对变量的监控都将被取消。
故当事务执行失败后,需重新执行WATCH命令对变量进行监控,并开启新的事务进行操作
Jedis
pom文件
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.2.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.58</version> </dependency>
java测试类
@Test
public void Ping() {
Jedis jedis = new Jedis("192.168.1.107",6379);
System.out.println("连接成功");
//查看服务是否运行
jedis.auth("123456");
System.out.println("服务正在运行: "+jedis.ping());
}
SpringBoot整合
Redis.conf
1)INCLUDES 包含
和Spring配置文件类似,可以通过includes包含,redis.conf 可以作为总文件,可以包含其他文件!
2)NETWORK 网络配置
bind 127.0.0.1 # 绑定的ip
protected-mode yes # 保护模式
port 6379 # 默认端口
3)GENERAL 通用
默认情况下,Redis不作为守护进程运行。需要开启的话,改为 yes
daemonize yes
可通过upstart和systemd管理Redis守护进程
supervised no
以后台进程方式运行redis,则需要指定pid 文件
pidfile /var/run/redis_6379.pid
日志级别。可选项有: # debug(记录大量日志信息,适用于开发、测试阶段); # verbose(较多日志信息);# notice(适量日志信息,使用于生产环境); # warning(仅有部分重要、关键信息才会被记录)。
loglevel notice
logfile “” # 日志文件的位置,当指定为空字符串时,为标准输出
databases 16 # 设置数据库的数目。默认的数据库是DB 0
always-show-logo yes # 是否总是显示logo
4)SNAPSHOPTING 快照
900秒(15分钟)内至少1个key值改变(则进行数据库保存–持久化)
save 900 1
300秒(5分钟)内至少10个key值改变(则进行数据库保存–持久化)
save 300 10
60秒(1分钟)内至少10000个key值改变(则进行数据库保存–持久化)
save 60 10000
stop-writes-on-bgsave-error yes
持久化出现错误后,是否依然进行继续进行工作
rdbcompression yes
使用压缩rdb文件 yes:压缩,但是需要一些cpu的消耗。no:不压 缩,需要更多的磁盘空间
rdbchecksum yes
是否校验rdb文件,更有利于文件的容错性,但是在保存rdb文件的时 候,会有大概10%的性能损耗
dbfilename dump.rdb
dbfilenamerdb文件名称 dir ./ # dir 数据目录,数据库的写入会在这个目录。rdb、aof文件也会写在这个目录
5)SECURITY安全
启动redis
连接客户端
获得和设置密码
config get requirepass
config set requirepass “123456”
测试ping,发现需要验证
127.0.0.1:6379> ping
NOAUTH Authentication required. # 验证 127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> ping
PONG
6)限制
maxclients 10000
设置能连上redis的最大客户端连接数量
maxmemory
redis配置的最大内存容量
maxmemory-policy noeviction
maxmemory-policy 内存达到上限的处理策略
volatile-lru:利用LRU算法移除设置过过期时间的key。 volatile-random:随机移除设置过过期时间的key。 volatile-ttl:移除即将过期的key,根据最近过期时间来删除(辅以TTL)
allkeys-lru:利用LRU算法移除任何key。
allkeys-random:随机移除任何key。
noeviction:不移除任何key,只是返回一个写错误。
7)append only 模式
appendonly no
是否以append only模式作为持久化方式,默认使用的是rdb方式持久化,这种 方式在许多应用中已经足够用了
appendfilename “appendonly.aof”
appendfilename AOF 文件名称
appendfsync everysec
appendfsync aof持久化策略的配置
no表示不执行fsync,由操作系统保证数据同步到磁盘,速度最快。
always表示每次写入都执行fsync,以保证数据同步到磁盘。
everysec表示每秒执行一次fsync,可能会导致丢失这1s数据。
常见的配置介绍
Redis持久化
Redis 是内存数据库,如果不将内存中的数据库状态保存到磁盘,那么一旦服务器进程退出,服务器中
的数据库状态也会消失。所以 Redis 提供了持久化功能!
1)RDB
什么是RDB?
在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快
照文件直接读到内存里。
Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程
都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的。
这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那
RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。
Fork
Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量,环境变量,程序计数器等)
数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。
如何触发RDB快照
如何恢复
2)AOF (Append Only File)追加文件
是什么
以日志的形式来记录每个写操作,将Redis执行过的所有指令记录下来(读操作不记录),只许追加文件
但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件
的内容将写指令从前到后执行一次以完成数据的恢复工作
Aof保存的是 appendonly.aof 文件
配置
AOF 启动/修复/恢复
优点和缺点
总结:
Redis 发布订阅
1)是什么
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
Redis 客户端可以订阅任意数量的频道。
2)命令
3)测试
发布者向 hjr 发送了信息
订阅者接收到信息
4)原理
Redis主从复制
(以下命令配置只是临时的,应该在redis.conf文件配置才是永久的)
1)概念
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点
(master/leader),后者称为从节点(slave/follower);数据的复制是单向的,只能由主节点到从节点。
Master以写为主,Slave 以读为主。
默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从
节点只能有一个主节点。
2)作用:
主从复制的作用主要包括:
1、数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
redis 127.0.0.1:6379> PUBLISH redisChat “Hello,Redis” (integer) 1 redis 127.0.0.1:6379> PUBLISH redisChat “Hello,Kuangshen” (integer) 1 # 订阅者的客户端会显示如下消息 1) “message” 2) “redisChat” 3) “Hello,Redis” 1) “message” 2) “redisChat” 3) “Hello,Kuangshen” 123456789101112
2、故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务
的冗余。
3、负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务
(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写
少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
4、高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是
Redis高可用的基础。
3)环境配置
配从库不配主库,从库配置:
slaveof 主库ip 主库端口 # 配置主从
Info replication # 查看信息
从库每次与 master 断开之后,都需要重新连接,除非你配置进 redis.conf 文件!
4)一主二从
一开始都是master节点
配置为一个Master 两个Slave
在主机设置值,在从机都可以取到!从机不能写值!
5)层层链路
5)谋朝篡位(从机当主机)
6)复制原理
哨兵模式
1)概念:
主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工
干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑
哨兵模式。Redis从2.8开始正式提供了Sentinel(哨兵) 架构来解决这个问题。
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独
立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
2)配置测试
3)哨兵模式的优缺点
4)哨兵配置说明
缓存穿透和雪崩
1)缓存穿透
概念
解决办法
2)缓存击穿
概念
解决方案
3)缓存雪崩
解决方案