数据库:提前定义schema类型,字节长度,是为了存储提前占位,改方便
表的数据变大,性能下降:
如果有索引,增删改会慢,1个或少量查询依然很快,并发大的时候会受磁盘带宽影响速度

数据在磁盘和内存的体积不一样
磁盘中没指针

https://db-engines.com/en/ 数据库排名,

redis类型:string、hash、list、set、sortset、bitmap、
memcached没有类型是json,类型的意义,想取list中的某一个元素,memcached需要返回所有数据,而redis每个类型有对应的方法
大数据名词:计算向数据移动(计算在提供数据方)

redis安装流程
1.yum install wget
2.wget http://download.redis....在redis官网找download,右击链接复制安装路径
3.tar xf redis.tar.gz
4.看redis的README.md
5.在redis源码目录make (会报错)
yum install gcc
makedistclean (清除之前的报错)
make
6.redis 的 src生成了可执行程序
7.make install PREFIX=(要安装成服务的路径)
路径的bin就会有可执行程序
8.vi /etc/profile
export REDIS_HOME=(要安装成服务的路径)
export PATH=$PATH:$REDIS_HOME/bin
source /etc/profile
9.cd utils
./install_server.sh
a)一个物理机可以有多个redis进程,通过端口号区分
b) 多个实例各自的配置文件、持久化目录
10.service redis_6379 start/stop/status

redis是单进程、单线程、单实例的,并发很多请求怎样变的快的???查看2000面试题
epoll
socket非阻塞,NIO 同步非阻塞
多路复用 NIO

redis
redis.cn

bio:一个连接一个线程,阻塞的,cpu调度成本高、内存成本高
nio:1.一个线程,一直循环去调内核获取连接,不阻塞
2.线程去调selector一次,把连接都传给selector他去等待连接,等待上后告诉线程
3.线程去调epolll一次,epoll里有个共享空间存连接的信息,有个红黑树与链表


redis是单线程处理用户请求,单线程可以保证顺序型

redis默认16个库,0-15
每个库隔离

redis-cli -p 6379
使用help @... 按tab 提示

一、字符串:
help @string
包括string、数值、bitmap
一下为字符串的方法
set key value NX不存在的创建,存在了不动
set key value XX 存在了更新,不存在不动
用于分布式锁
mset key value key value
mget key key 可原子性,一个key没成功都不成功
append key value value追加字符串
getrange key start end 截取字符串,正反向索引
setrange key start value
strlen 字符串长度
type 返回存进去的类型,“11”为string
object encodind 返回编码类型 “11”为int
incr 为数值累加,可以应用秒杀、点赞量
setbit key offset value。 00000000 set key 1 1变为01000000第一位变成1
strlen是1如果set key 9 1。strlen变为2因为超过8位
redis是二进制安全的,中文是字节数组,客户端查看中文字符集相同就一样
redis-cli - -raw 可将中文展示出来,但需要注意xshell的字节码要和存的时候一致,utf-8,GBK
bitmap操作
bitpos
bitcount 统计区间1的数量
bittop and/or newkey k1 k2 可以按位与/或操作
场景:
1、用户系统、统计用户的登陆天数,窗口随机
  关系型数据库需要至少三个字段 id,用户,登陆时间
  redis可以用365位表示一年的天数,只有不到50个字节,key为用户名,value为bit
  bitcount可以进行窗口统计
2、618登陆就送礼物,有两亿用户,备多少礼物
可以统计去年登陆的用户量,活跃用户数(618、619、620登录表示活跃)
key为日期20210618 value为bit,每个用户占一位
bittop 或运算,20210618、20210619、20210620这几个key统计到另一个key中
再biycount统计活跃数

二、list
help @list

lpush左边push
rpush 右边push
lpop 与lpush同向,后进先出,栈;与rpush逆向,先进先出,队列
rpop同理

lrange key start end 从左往右取
lindex
lset key value
lrem key count value 根据value移除count个,count为负数是从右往左

bpop key timeout 阻塞弹出,是个阻塞队列,第一个先阻塞的先拿,第二个继续等待下一次set key,单播队列
ltrim key start end 截取start end之间的

三、hash,map
hset key filed(字段:value的key)
其他的方法类似其他类型,需要指定fild字段

四、set 无序,不可重复
sadd
sinter k1 k2 取k1k2 交集,打印
sinterstore dest k1 k2。取k1 k2 交集放到dest中
sunion 并集
sdiff k1 k2 差集
srandmember k1 count 随机取count个,count为正随机取出,不可能重复;负数一定满足count的数量,可能重复。
场景:抽奖,一共有10个礼物,set里放人,count为10则可能1个人多个礼物,-10则1个人只能有1个礼物。
spop key 随机在key中取一个,取出就不会再出现
五、sortedset
可以排序的set,指定某个维度排序
zadd key score member,需给出分值
zcount min max 统计分值min-max
zrange key 0 -1 按分值顺序取出
zrangescore key min mac 按分值区间顺序取出
zrevrange 反序取出
zscore key member 取出member的分值
zrank k1 member 取出member的排名
zincrby key number member 将member分值加number
zunionstore destkey keys weight(权重) sum/min/max
并集,默认权重为1,带上权重需要乘权重后合并,默认分值sum合并
排序底层是怎么实现的?
skip list 跳表,将元素分为多层,底层所有元素,上层元素少
3
3。 7
3。5。7。 9
随机造层

redis 管道
可以用nc localhost 6379连接
管道:echo -e "set k2 99\nget k2" |nc localhost 6379 连接、set、get

redis 发布订阅
help @pubsub
publish key message 发布消息
subscribe key 监听key
监听在发布前才能监听到


redis事物
multi 开启事物
exec提交事物
一个客户端的事物不会影响其他客户端
谁先exec先到达谁先执行
redis没有回滚,可以先watch监听某个key,key发生变化了会回滚事物

redis bloom过滤器
可以防止缓存穿透
搜一些没有的东西,就会直接访问数据库,造成数据库压力
先把数据库中所有元素BF.add进去,用hash标记bitmap
BF.Exists 1数据库有,0数据库没有,数据库没有的可直接返回空
数据库有的向bitmap中标记,没被标记的不去数据库查
请求的可能被误标记???hash可能碰撞

redis作为数据库和缓存的区别
缓存数据不重要,不是全量的,随着访问变化,存热数据
随着访问变化,淘汰冷数据

maxmem最大内存
lru未使用时间长的、lfu使用次数短的内存满了回收策略
默认策略报错
allkeys lru回收最少使用的key
volatile lru回收最少使用的key 只在会过期的key中
allkeys random 随机回收
volatile random 随机回收 只在会过期的key中
ttl回收马上要过期的key

get key的时候不会延长过期时间,修改set key的时候如果不指定过期时间则会成为永久
expire可以倒计时,expireat可以指定时间

过期原理:
主动:如果每秒都所有key检测影响cpu性能
被动:如果等get了再去检测可能一直不get会占用内存
如下
1.测试随机20个key看是否过期
2.删除所有过期的
3.如果多于25%过期的key重复1


grep管道
前一个命令的输出最为后一个命令的输入
会创建子进程
子进程修改的数据不会影响父进程
父进程修改数据也不会影响子进程
num++|grep echo ok
num++没有在后边用到不会执行

备份数据时防止备份时修改数据,可以创建一个子进程,父进程修改数据不会影响子进程
创建数据子进程拷贝一份,(指针)
父进程如果修改时会copy on write 复制一份,原来的指针保留

RDB
save
bgsave后台保存,fork创建子进程
生成dump.rdp
丢失数据多

AOF
redis的写操作记录到文件中,丢失数据少
体量大,恢复慢
4.0以前:删除抵消命令,合并重复命令
4.0之后将老的数据RDB,到aof文件中,再增量aof指令,理由了rdb的快,和aop的全量

RDB与AOF可以都开启


单节点问题:
单点故障
容量有限
压力大

主备:全量镜像(不能解决压力问题)
一个主节点几个备用节点,主挂了备用来
写几个节点都写,读可以分离
容量问题可以将数据根据业务拆分
AKF
X:全量镜像
Y:业务划分数据
Z:一个业务可以分为不同库:用户每1000个存一个库

主备一变多:需要数据一致性
1.所有节点阻塞直到数据一致:强一致性,会造成一个节点超时都不能返回。同步阻塞
2.如果可以容忍数据丢失:异步,先主节点写好后通知备机异步写。异步数据丢失
3.可以先写到Kafka,如果Kafka接受到则返回客户端成功,kafka再去写备机,可以不丢数据,异步,最终一致性

主备:客户端只会访问主,主挂了再访问备
主从:客户端可以访问备机
一个主还是单点,对主做高可用

使用奇数台,可以过半判断是否故障,节省成本

CAP
一致性、可用性、分区容忍性,三选二


主从复制
在从节点执行命令
5.0以前使用:slaveof ip port命令实现主从
5.0之后使用:replicaop ip port
或者启动时--replicaop ip port
或者配置文件里配置replicaop ip port
会先把从数据清空,然后再同步主的数据
主挂了,可以执行replicaop no one 从变为主,需要人工执行
replica-serve-srale-data yes同步数据时从节点可以查询,no:不可查询
replica-read-only从节点只能读
每次从节点重新需要同步数据,主维护队列。从挂了主把队列里的数据同步,队列不行就全量

Sentinel哨兵
sentinel monitor mymaster ip prot。配置监控主节点
redis-sentinel.sh
或者redis-server --sentinel
主挂掉会自动选出另一个主
哨兵通过发布订阅来发现其他从节点


数据分片:
1.hash+取模,缺陷模值固定,不容易扩展
2.random 随机机器消息队列可以保证可以能消费lpush rpop
3.一致性哈希,md5,hash 没有取模,需要数据和节点数参与计算,加节点不会造成全局洗牌,新增节点会造成一部分数据不会命中,可以每次取附近的两个节点

客户端链接lvs暴露vip,lvs调用多个代理,代理去调用后端

预分区(无主模型、主主模型)
可以预先分为很多分区,增节点可以向新节点分配几个分区,少量数据迁移
redis每个分区都有分区的信息,每个分区都有哪些数据


perdixy
代理多个哨兵,

redis-cli —cluster create IP:port IP:port
把数据分到不同节点,访问时自动跳到改节点
redia-cli -c -p
去连接,会自动跳


缓存击穿
key丢失的一瞬间很多连接过来访问到数据库
可以setnx 不存在的时候去set,相当于一把锁,第一个连接过来就set上了,其他的不访问数据库,其他没拿到锁睡一会就有key了
可能会死锁,第一个拿到锁挂了,导致其他连接等待,可以把锁加过期时间
过期时间可能超时,还没set好就释放锁,可以起另一个线程监听key是否设置成功,没设置成功延长过期时间


穿透
客户端访问的数据是系统根本不存在的
布隆过滤器
只能增加不能删除

雪崩
大量key同时失效
随机过期时间
如果不能随机过期时间,则参考击穿方案
可以在更新时间点,将客户端限流

分布式锁
可以setnx 不存在的时候去set,相当于一把锁,第一个连接过来就set上了,其他的不访问数据库,其他没拿到锁睡一会就有key了
可能会死锁,第一个拿到锁挂了,导致其他连接等待,可以把锁加过期时间
过期时间可能超时,还没set好就释放锁,可以起另一个线程监听key是否设置成功,没设置成功延长过期时间
最好使用zookeeper

客户连接
jedis

lettuce


redistemplate key会有乱码
stringredistemplate key不会乱码,但是只能存string
也可以用低阶api,用redisconnect 需要set和get字节数组

value是对象时
需要引入json,注入objectmapper
new一个Jackson2HashMapper用对象去.tohash就可以放进去
也可以用.convertValue将map转为对象
使用stringredistemplate如果hash结构有不是string,如int类型可以使用setHashSerializer(Jsckson2redisSeeializer)去修改默认序列化,就可以存不是string的类型了

自定义template
每次都序列化很麻烦,写个@confihuration中的@bean将stringtemplate处理好后返回,注入时@Qualifier(自己的bean)

redis的发布订阅
.converandsend
.subscribe