本质:读、写
随着数据不断的增量其一直在围绕解决读、写问题。
nosql=not only sql 泛指非关系型数据库
关系型数据库:表格、行、列
很多数据类型用户的个人信息,社交网络,地理位置。这些数据类型的存储不需要一个固定的格式。不需要多余的操作就可以横向扩展的。
3V是问题的描述
3高是对程序的要求
1. KV键值对
新浪:Redis
美团:Redis+Tair
2.文档型数据库(bson格式)
MongoDB: 是一个基于分布式文件存储的数据库,C++编写,主要用来处理大量的文档;是一个介于关系型数据库和非关系型中中间的产品;其是非关系型数据库中功能最丰富,最像关系型数据库的。
3. 列存储数据库
4 . 图关系数据库

// 需要用到 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
所有命令h开头
应用:数据结构适合存储javaBean
字符串列表,按照插入顺序排序,类似于LinkList 可以在头部、尾部插入数据(列表)
数据结构:队列、栈

都是l开头的命令
插入左侧:
lpush key value1[value2] 左边插入
lpush list1 k1
lpush list1 k2
lpush list2 k1
插入右侧
rpush key value1[value2] 右边插入
rpush list1 k4
列表长度
llen key 获取列表长度
获取范围内元素
lrange key start stop 获取范围内的元素
0:第一个元素
-1:最后一个元素
-2:倒数第二个元素
移除元素左
lpop key 从左侧移除第一个元素
移除元素左
rpop key 从右侧移除第一个元素
通过索引查找元素
lindex key index 通过索引获取列表的元素0
移除指定元素:count 个value
lrem key count value 移除对应list中count 个value
注:one one two three–>lrem list 2 one -->two three
截取
ltrim key start top 只保留指定区间内的元素,其余都被删除。
rtrim key start top
移除放入
rpoplpush source desction 移除源list最后一个元素放入目标list左
设置指定索引的值(更新)
前置条件:list必须是存在的,index也必须是有效存在的。不存在报错。
lset key index value 设置索引指定元素的值
blpop key 从左侧移除并获取第一个元素。列表没有元素会阻塞等待超时或者弹出元素。
brpop key 从右侧移除并获取第一个元素。列表没有元素会阻塞等待超时或者弹出元素。
在指定位置前后插入数据
linsert key before||after oldvalue newvalue 值指定元素的值前||后插入数据。
任务队列:
rpoplpush a1 a2 : a1最后的元素调到a2的右侧
rpoplpush a1 a2 :循环列表。将最后的元素移动到最左侧
类似java中hashTable------其低层使用了intset 和hashtable 数据结构
所有命令为s开头
添加
sadd key menmber1[menmber2] 向集合中添加一个或多个数据
返回所有元素
smembers key 返回集合中所有的元素
是否存在
sismember key menmber 判断集合中是否存在
集合个数
scard key
移除指定元素
srem key member1 [menmber2] 移除集合中一个或多个成员
随机返回元素(抽奖)
srandmember key [count] 返回集合中一个或多个随机数
随机移除元素
spop key [count] 移除并返回集合中的一个或多个随机成员
移动元素到另外一个集合
smove source destination member 移动集合中的元素到另一个集合中
差集:
sdiff key1 key2 -------- key1相对于key2的差集
sdiffstore destination key1 key2 将返回的结果集存入destination
交集:
sinter key1 key2
sintetstore destination key1 key2 将返回的结果集存入destination
并集:
sunion key1 key2
sunionstore destination key1 key2 将返回的结果集存入destination
唯一、有序。每个元素都会关联一个double类型分数。集合通过标识数来排序。集合的成员是唯一的,但是标识数可以重复的
每一个value 前有一个分数标识
三大特殊数据类型
geospatial 地理位置
redis3.2以后才有的
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"
Hyperloglog 基数
Bitmaps
位存储
统计用户信息活跃不活跃;登录不登录,打卡未打卡。只要其为两种状态的都可用Bitmaps,
Bitmaps位图。数据结构都是操作二进制位来进行记录,就只有0 1两个状态
本质:一组指令的集合,其顺序去执行
Redis 单条 命令有原子性,但Redis事务不保证原子性。(其中命令编译异常(命令错误)会停止;运行异常在会继续执行)
一次性、顺序性、排他性!执行一系列命令。
事务阶段:
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 去监视可以当做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
java redis中存入数据,会默认对其进行java序列化后存入。
更改存入数据的序列化
java:
String: ValueOperations
Hash: HashOperations
ListOperations
[]
----------------------------------------------------springboot整合----------------------------------------
见springboot
可包含其他文件

网络
通用
快照rdb
save 900 1 900s内至少1个key发生修改就就持久化
save 300 10 同上
save 60 10000 同上
安全

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

AOF
将所有的命令记录下来,history ,恢复的时候把这些命令全部执行一遍即可。
以日志的形式记录每个写操作,将Redis执行过的所有指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初就会读取该文件重新构建数据。换言之,redis重启的话就根据日志文件内容将写指令从前到后执行一次以完成数据恢复工作。
修复 (rdb与aof文件错位后的修改)

订阅者
渠道
发送者

命令:
publish channel message 发布 —主动推送
subscribe channel 订阅
应用:消息推送。公众号模式

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

启动多个节点:
./redis-server + 配置文件
客户端链接不同节点:
./redis-cli -p
默认情况下都是主节点

命令:slaveof -host -p

设置完成后查看主机信息

# slaveof
有密码则设置:
masterauth
当主节点断开不存在,则从节点可以设置自己为主节点,其他从节点需要手动连接到当主节点
命令:slaveof on one
主机可以写,从机只能读,主机所有的数据信息都会保存到从机

Slave 启动成功后连接到Master后会发送一个sync命令同步
Master接到命令后,启动后台的存盘进程,同时收集所有接受到的用于修改数据集命令后,在后台进程执行完毕之后,master将传送整个数据文件到slave,并完成一次完全同步。
全量复制:slave服务在接收到数据库文件数据后,将其存盘并加载到内存中
增量复制:master继续将所有收集到的修改命令依次传给slave,完成同步
只要是重新连接master,一次完全同步将被自动执行
谋朝篡位自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转为主库
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行多个Redis实例。

一个哨兵开一个进程去监控所有节点,如果当前这个哨兵挂了怎么办

假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主管的认为主服务器不可用,这个现象称为主管下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定的值时,那么哨兵直接会进行一次投票。投票的结果由一个哨兵发起,进行failover[故障转移]操作,切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器切换到主服务器,这个过程称为客观下线。
./redis-sentinel 配置文件
主节点关闭后,哨兵自动故障转移重新设置了主节点,前主节点重启后就变为了从节点

集群内置了16384个slot,并把它们平均非配个各个主节点。当redis集群存放一个数据(key-value)时,redis会先对key进行crc16算法,将得到的结果对16384进行求余,这个余数对应[0-16384]其中一个槽,进而决定key-value存那个节点;一旦其中一个主节点挂了,slot则无法使用,那么集群就无法正常工作。

6份redis

./redis-cli --cluster create 192.168.79.128: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
cluster-replicas :一个主节点后面有几个从节点

cluster nodes

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
缓存穿透的概念很简单,用户想要查询一个数据,发现Reds内存库中没有,也就是缓存没有命中,于是向持久层数据库查询,发现也没有,于是本次查询失败,当用户很多的时候,缓存都没有命中,就是持续查数据库就会给数据库造成很大的压力,这时候就相当于出现了缓存穿透。

这里需要注意和缓存击穿的区别,缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对一个点进行访问,这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在屏障上凿开一个洞。
从缓存层面来看,没有设置过期时间,不会出现key过期所产生的问题
分布式锁:使用分布式锁,保证对于每一个key同时只有一个线程去查询后端服务,其他线程没有获得分布式事务锁的权限,只需等待。
是指某一个时间段,缓存集中过期失效;Redis宕机
redis有可能挂掉,那就多增加几台
缓存失效后,用过加锁或者队列来控制读数据库写缓存的线程数量
就是在正式部署之前,我先把可能数据先访问一遍。这样部分可能大量访问的数据就会加载到缓存中,在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。
- 当主机服务器宕机后,需要手动把一台服务器切换为主服务器。费时费力造成一段时间内服务不可用
- 哨兵模式是主从模式的升级版。哨兵是一个独立进程运行。
- 主要解决主节点挂了后,在从节点自动选出一位主节点来继续运行,实现**主动故障转移**。
- redis在3.0后加入了集群模式,实现了redis的分布式存储,也就是说每台redis节点上存储不同的内容
- 其继承了主从的读、写分离和哨兵的故障转移的优点
- 方便横向扩容