性能测试工具


redis-benchmark -h host -p port -c connections -n requests  
-h host:指定Redis服务器的主机名或IP地址。
-p port:指定Redis服务器的端口号。
-c connections:指定并发连接数,即同时向服务器发起的连接数量。
-n requests:指定总的请求数量,即测试期间每个连接向服务器发送的请求数量。
EG:
redis-benchmark -h localhost -p 6379 -c 100 -n 10000

2.默认有十六个数据库,用的是第0个,可以在配置文件看到,也能使用命令切换。
切换到第一个数据库,切换只对当前客户端生效。意味着不同客户端可以同时选择不同的数据库

 SELECT 1

查看数据库大小

info

查看数据库所有的key

KEYS *

列出所有以 user: 开头的键。

KEYS user:*

清空全部和当前数据库的key

FLUSHDB
FLUSHALL

Redis是单线程的,是很快的,基于内存操作的,CPU不是它的瓶颈而是内存和网络带宽。
Redis为什么单线程还这么快?
内存操作:Redis 是基于内存的数据库,因此它的主要操作是内存读写,这些操作速度非常快,不需要考虑线程切换和同步带来的开销。

非阻塞 I/O 多路复用:Redis 使用非阻塞 I/O 和多路复用技术,通过单个线程来处理多个客户端连接,这样可以最大化地利用系统资源,减少了线程创建、销毁和上下文切换的开销。

事件驱动模型:Redis 使用了事件驱动模型,通过 epoll、kqueue 等机制来监听文件描述符上的事件,当有事件发生时,立即处理,这样能够高效地响应客户端请求。

无锁设计:Redis 在实现过程中尽可能地避免了使用锁,比如在读写操作中使用了原子操作,减少了锁竞争带来的性能损失。

基于主线程的多个工作队列:Redis 使用了多个工作队列,比如客户端请求队列、定时任务队列等,这些队列由主线程轮询处理,避免了多线程之间的竞争和同步开销。

Redis的数据都在内存中。多线程切换会发生频繁上下文切换从而降低效率

五大数据类型,三种特殊数据类型
看官网文档(有中文官方版本的)
可以当数据库、缓存、消息中间件MQ

Redis-key
读和写key

SET mykey "Hello"
GET mykey

查看键是否存在

EXISTS mykey

移除key

DEL mykey

查看当前数据库所有key

KEYS *

设置过期时间 ttl命令(单位是秒)

SET mykey "value"
EXPIRE mykey 60

type-查看key的数据类型

SET mykey "value"
TYPE mykey

String(字符串类型)

APPEND字符串追加

STRLEN-获取字符串长度

incr-把键的值加1,反过来是decr ---可以设置步长
flushdb
set key
keys *

getrange -获取指定范围的字符串,截取字符串
0- -1 ,-1代码结尾,就是说这样可以输出全部字符串
SETRANGE-字符串替换
setex-多久后过期
setnx-如果这个键不存在就设置,分布式锁中会常常使用
mset-批量设置值
mget-批量get值
msetnx-不存在的时候设置,mset+setnx可以这么理解应该,这是原子性的操作,
这件键要么一起成功要么一起失败
使用set保存一个对象,巧妙使用:号

getset-先get再set,如果存在就获取原来的然后设置新的,否在返回nil

List类型-可以当栈和队列玩
所有相关的命令都是L开头的
lpush-插入到列表左边(头部)
lrange-获取指定范围的值
lrpush-从尾部(右边插入)
---Redis命令不区分大小写--
lpop-弹出
rpop-尾部弹出
lindex-获取list的某个下标对应的值
llen-查看列表长度
lrem-remove a key from the list
ltrim-trim the list,截取一部分,通过下标截取指定长度
rpoplpush-移除最后一个元素然后把这个元素添加到另一个列表
lset -指定下标的值替换为另外一个值,是更新操作
=判断一个列表是否存在
linsert-在某个key的前面或者后面插入一个值
总结:就是一个链表

set集合-无序不重复集合
都是S开头的
sadd-添加集合元素
smembers-查看全部成员
sismember-查看这个成员是否存在
scard-查看集合大小
srem-删除里面的元素
srandmember-随机获取一个或指定个数的元素
spop-随机弹出一个元素
smove-将一个指定的值移动到另外一个集合
sdiff-查看差集
sinter-交集
sunion-并集

Hash(Map集合)-key-Map(k-v)集合:面向key-value的
hset-创建一个map
hget-
hmset-
hmget-
hgetall-
hdel-
hlen-
hexists
hkeys-获取keySet
hvals-
hincrby-
hsetnx-
应用:拿来保存对象

Zset(score set,有序集合,通过一个分数来排序),在set的基础上面加一个值
zadd-
zrange-
排序如何实现?
zrangebyscore-限制指定范围分数的键,-inf,+inf表示无穷
--默认是升序--
zrem-移除元素
zcard-查看大小
zrevrange-降序查询
zcount-判断在这个区间的值有多少个

geospacial 地理位置,可以推算地理位置信息,比如两地之间的距离,指定范围的人
geoadd-添加地理位置(两级无法直接添加)
geopos-获取某个地方的经纬
geodist-两个坐标之间的距离
georadius-通过半径来查询(附近的人,就是查询某地指定半径内包含的地方,可以加参数限制数量
GEORADIUSBYMEMBER-找出位于指定元素指定范围内的元素
geohash-把坐标转换成一个字符串
----底层的实现原理其实就是zset,所以也可以使用它的命令--
zrem-可以拿来移除一个坐标

Hyperloglog-基数统计
--优点--只占用常数的内存
--基数的概念,不重复的元素--
--可以拿来统计网页的点击量
--有0.81%的错误率--忽略不计
pfadd-
pfcount-
pfmerge-

Bitmap-位存储
一般拿来统计,比如打卡和没打卡啥的
是一种数据结构,里面的玩意只有0和1两种结构
setbit-
bitcount-

事务
原子性-要么一起发生,要么一起失败
Redis单条命令是保证原子性的,但是事务不保证原子性。
Redis事务的本质-一组命令一起执行,在执行的过程中会按照顺序执行
Redis事务没有隔离级别的概念
入队的时候并没有执行,exec的时候才会执行
事务的阶段:
1.开启事务-multi
2.命令入队-就是直接输入要执行的命令,然后回车
3.执行事务-exec

discard-取消事务,就是命令入队的过程的时候直接终止

编译型异常(命令写错了)-事务中所有的命令都不会被执行
运行时异常(命令执行的时候出现的异常)-别的正确的命令会正常执行,只有有错误的命令不会被执行

监控
悲观锁和乐观锁
悲观锁:干啥的加锁,很影响性能
乐观锁:认为什么时候都不会出现问题,所以不会上锁。更新数据的时候会去判断是否有人修改过这个数据,会使用一个version字段控制
watch-监视某个键的值
就是在事务开始之前进行监视,然后开始事务,如果这个事务在执行之前这个值被修改了, 那么事务就会执行失败。这是用乐观锁实现的。
unwatch-放弃监视,然后可以重新操作,就是获取最新版本的呗

Jedis-官方推荐的java操作redis的工具包,就是一个jar包
1.去mvn仓库扒下来,放到maven项目中
编码测试
-连接数据库
new Jedis对象,这个类的方法与命令有对应关系
如果操作事务的话,需要建立Transaction对象

与SpringBoot的整合
springBoot操作数据都是spring-data-
springBoot2.X之后,jedis被变成了lettuce,就是说底层已经改变了。
jedis-直连的,多个线程操作是不安全的,像BIO
lettuce-采用netty,实现可以在多个线程中共享像NIO
原码分析-

Redis.conf详解
bind-绑定的IP,可以配置才能远程访问
端口的修改
是否以守护进程方式运行(默认是no,我们需要改成yes)
配置文件的pid文件,pidfile-
日志级别
logfile-生成的日志文件名
database 16 数据库的数量
是否总是显示logo
--快照--
持久化,在规定的时间内,执行了多少次操作然后进行持久化到文件.rdb.aof
save 900 1-如果900秒内至少有一个key进行了修改那么我们就进行持久化操作
持久化出现错误是否还继续工作
是否压缩rdb文件
是否校验rdb文件
设置密码 requirepass auth
限制CLIENT-设置最大客户端数量
内存到达上限之后的处理策略
默认是不开AOF模式的,而是使用RDB模式
appendonly no
appendfilename -持久化文件的名字

Redis持久化-这是重点
redis是内存数据库,不持久化的话断电数据就没了
持久化的时候会fork一个子进程去IO。
主进程不进行IO,保证性能
rdb保存的文件名默认是 dump.rdb
aof保存的文件名默认是 appendonly.aof

rdb
触发机制:
1.save的规则满足的时候
2.flushall之后
3.退出redis
这三种情况都会进行持久化
恢复rdb文件,把rdb文件放到redis启动目录就可以了,redis启动的时候会自动检查有没有持久化的文件,如果有就会进行恢复。
生产环境一般会进行rdb文件的备份
优点:
1.适合大规模数据恢复
2.对数据的完整性要求不高
3.速度比AOF快
缺点:
1.需要一定的时间间隔进行操作,如果意外挂了,就没有最后一次持久化
2.fork进程的时候,会消耗一定内存

AOF
将我们执行的写数据命令都记录下来到日志里,启动的时候把这些命令再执行一遍
这模式默认是不开启的,可以在配置文件里面开启
持久化的策略,默认是一秒一次
重写的规则,是否同步啥的
如果保存的日志文件(appendonly.aof)被破坏了会怎么样?(就是那堆命令被改了)
redis-check-aof 拿来修复这个文件
优点
1.每一次修改都同步,文件完整性更好
2.每秒同步一次,可能丢失一秒的数据
3.从不同步,效率最高
缺点
1.相对于数据文件来说,aof远远大于rdb,修复的数据也比rdb慢
2.AOF的运行效率也比rdb慢
重写规则说明,日志文件大小到一定程度之后就会开启一个新进程来重写这个文件
aof默认是日志无限追加

这是可以两个都开启的

redis发布-订阅
一种消息通信模式
redis客户端可以订阅任意数量的频道
1.消息发送者
2.频道
3.消息订阅者
相关的命令
-订阅频道
-将信息发送到一个频道
-退订频道
订阅一个频道之后自动进入监听状态,
收到的一条消息会有三个属性,message-sender-content
底层实现-(自己百度了解一下-字典和链表
应用场景:
实时消息系统
实时聊天-频道当聊天室
订阅-关注系统

主从复制
把一台服务器(主结点)的数据,复制 到几台别的服务器(从结点)
复制是单向的
主从复制,读写分离
主从复制的作用:
1.数据冗余
2.故障恢复
3.负载均衡
4.高可用(集群)
--哨兵模式--
一般至少是一主二从
单台redis内存不应该超过20个G(超过就使用集群)
主节点和从节点是一对多
单击默认是主节点
info replication-查看当前库的信息,看看是主是从

单机玩集群需要修改的地方
端口
后台运行
logfile
rdb的文件名(备份文件的名字)
pidfile的名字

一般只需要配置从机,不需要配置主机
slaveof-认老大
真实的配置应该是在配置文件中配,这样的配置才是永久的
就是修改那个配置文件,重点搜索replication
---vim搜索某一个词----

主机可以写,从机只能读不能写
所有的读命令交给从机,写命令交给主机。
主机的数据会自动同步到从机
主机挂了之后从机还是从机,从机继续正常工作,就是说还能读,但是不能写了
如果是命令行配置的主从,重启之后设置就没用了,如果从机身份失效之后只要变回从机,数据立马写回来 ,就是自动同步。

复制原理
从机启动之后会给老大发送一个sync命令
主机收到之后启动后台的存盘进程,同时收集所有用于修改数据的命令,在后台执行完毕之后,主机将会传送整个数据文件到从机,并完成一次数据同步。从机收到文件之后把它加载到内存中。这是全量复制。
从机连接到主机的时候,自动完成一次全量复制。
增量复制-主机把收到的用于修改数据的命令交给从机,完成同步。

如果没有老大了,怎么让s
lave成为老大呢
slaveof no one -让自己成为主机,再让别的从机手动认自己。如果后面老大回来了,需要重新手动配置
哨兵模式出来之前这些都是手动完成的。

哨兵模式(自动选老大的模式)
能够监控主机是否故障,坏了自动选择老大。
redis提供了哨兵的命令,它是一个独立的进程,作为进程,它会独立运行。
原理是哨兵通过发送命令,等待redis服务器的响应,从而监控运行的多个redis实例。
如果哨兵死了怎么办呢?-多个哨兵,有主机挂掉的话会有故障转移然后就会投票选新的主机
-开启哨兵模式 :书写一个哨兵配置文件,sentinel.conf,说明要监控的主机
redis-sentinel sentinel.conf-启动哨兵
老大挂掉之后,哨兵选出新的老大,后面原来的老大再回来的话会自动成为新老大的从机
优点:
1.哨兵集群,一般基于主从复制模式,拥有所有主从复制的优点。
2.主从可以切换,故障可以转移,系统的可用性更好
3.是主从模式的升级,手动到自动
缺点:
1.Redis不好在线扩容,集群容量一旦达到上线,在线扩容会很麻烦
2.哨兵模式的配置很麻烦,可以有很多选择
-端口
-工作目录
-默认的主机节点
-默认的延时操作
-通知脚本

缓存穿透和雪崩
缓存穿透(太多的查询查不到)-就是查的很多数据都不在缓存中,会给持久层造成很大压力。
解决方案-
1.布隆过滤器,
2.缓存空对象-会浪费一点空间
缓存击穿(一个点被查太多了)-一个key非常热点,大并发集中对这一个点进行访问
解决方案:
1.设置热点数据永不过期
2.加互斥锁
缓存雪崩-一个时间段内,缓存集中过期失效。redis宕机
解决方案:
1.多加几台redis
2.限流降级
3.数据预热