基本知识:
- 默认16个数据库,默认使用第0个,可以用 select x 切换
- Redis是单线程的,数据放在内存中,多线程cpu切换耗时,所以单线程就可
- 硬盘存储数据和程序,运行速度慢
- 执行时cpu告诉硬盘将东西传输到内存上,cpu直接在内存上操作
- 功能数据库、缓存、消息中间件MQ
- 数据类型String、List、Set、哈希、sorted set 和三个不常用的
- String
- Set k v
- Setex k x v 设置过期时间x的值
- Setnx k v 如果不存在再设置
- Mset k1 v1 k2 v2….
- Msetnx k1 v1 k2 v2 是原子操作
- Get k
- Mget和上面一样批量操作
- Getset先获取再设置
- Incr key incrby k x 必须是Intreger类型
- Decr key decrby k x
- Getrange key x x 前后都包 0 -1 是查询全部
- Set k v
- List
- Lpush、rpush x k1 k2 k3…
- Lpop rpop
- 可以实现栈、队列、消息队列
- Lrange 0 -1 查看
- Ltrim 修建 截取后原来的就改变了
- Set
- Sadd *set **
- Smembers *set
- Sismember *set ** 判断是否这个set中的元素,存在返回1
- Scard *set 获取set集合中的元素个数
- Srem *set ** 移除set中的元素
- Smove *set1 *set2 ** 移到另一个集合中
- Sdiff *set1 *set2 查看两个集合不同的部分
- Sinter *set1 *set2 查看交集
- Sunion *set1 *set2 查看并集
- 例子:可以做共同关注之类的
- hash
- hset *hash k v
- hget *hash k
- hgetall *hash
- hdel *hash k
- sortedset
- zadd
- zrangebyscore *set -inf +inf withscores
- zrevrange xxx 倒序
Redis事务
- redis单条命令保证原子性,redis事务不保证原子性
- 没有隔离性的概念
- 一串命令像是队列等着入队,执行的时候才会执行
- 开启 multi
- 入队 就是上面的各种命令
- 执行 exec
- 取消 discard
- 编译期异常 比如命令写错了 直接全部都不执行
- 执行期异常 比如自增操作到字符上 这一条失败 其他会正常执行
- 在java中,可以try语句中正常执行,catch语句中打印错误信息并取消事务,在finally语句中关闭连接
Redis监控—乐观锁
watch ** 监视 可以当乐观锁 unwatch ** 取消监视
比如一串命令没有最后执行,此时数据被另外一个线程修改了 最后执行会失败
先unwatch解锁,再重新watch监视获取最新数据重新开启事务执行
Jedis,根据主机端口连接redis在idea中操作,命令差不多
SpringBoot整合
- boot2.x后,底层由jedis转为lettuce,
- jedis采用直连,多线程不安全,用jedis pool,类似BIO堵塞(×)
- lettuce采用netty,多线程下实例可以共享,类似NIO模式(×)
- RedisTemplate :
- OpsForValue(操作字符串)
- OpsForXX
- 默认使用jdk序列方式,可以自定义用json
- 真实开发中,应该会写一个RedisUtil类来封装原生的方法,方便开
RedisConfig
- bind 可以绑定ip
- port 端口设置
- darmonie 是否后台,默认 no,退出了线程就结束了
- loglevel notice 默认,可以改debug verbose warning
- requirepass可以设置密码,配置文件中改是永久性的,命令改下次启动就失效
- maxclients 能连接上的最大客户端数量
- maxmemory redis最大内存容量
- 超过内存后会根据设置的策略来对key作不同的操作
- appendonly no 默认rdb的持久化方式,不开启aof
Redis持久化
- 配置文件中 sava 60 5 比如这样设置就是60秒内修改5次会被持久化到dump.rdb文件中
- RDB:隔段时间fork一个子进程在进行持久化操作,但是宕机后最后没来得及持久化的数据会丢失
- AOF:appendonly 改为yes开启,把写的操作命令记下来appendonly.aof,每次启动,重新执行一次完成恢复
Redis发布订阅
- 消息发送者 -> 频道 -> 消息订阅者
- Publish channel message 发布消息在特定频道
- Subcribe channel 订阅了后有消息就会收到
- Redis server 维护了一个字典,字典的键是一个个channel,值是一个链表,保存订阅此频道的客户端
- 场景:
- 实时消息
- 订阅关注系统
- 复杂的用其他mq实现
Redis主从复制
- Master主节点进行写操作,Slave进行读操作,因为80%情况下在读,减缓服务器压力,一般容量超过20G就集群
- Info replication 可以看当前库信息
- 角色 master or salve 从机数量
- 默认情况下,每台redis服务器都是主机
- Slaveof ip 端口 配置从机 (命令,暂时Config中,replicaof ip 端口 ,masterauth ** 密码 永久
- 主机如果关闭,从机依旧显示连接原主机,可以获取内容,主机恢复,从机正常
- 从机关闭了,此时主机的从机数量就少了,主机的写操作,从机就拿不到了(命令),重新连接主机后还是能拿到所有信息
- 第一次或重新连接,会全量复制
- 连接后主机的操作,会增量复制到从机
- 层层链路
哨兵模式
- sentinel monitor ** ip 端口 【0-9A-Z.-_】 配置文件中写,监控, 然后启动哨兵
- 默认30秒,没有应答视作失联
- 多哨兵集群下,基于主从复制,主机挂了,哨兵联系不到会主观下线,其他哨兵也来尝试,都不行的话会客观下线,根据投票机制选出一个新的主机,后面主机连回来也会变为从机
- 缺点:redis不好在线扩容,哨兵配置麻烦
Redis缓存穿透
- 查询数据会先去缓存中查,如果没有会再去数据库中查询,如果都没有,多次查询后会给服务器很大压力,相当于缓存穿透(秒杀),一个点量太大
- 解决:
- 布隆过滤器,对查询的参数以hash存储,在查询前做一次过滤,不符合的直接过滤掉
- 是有一串二进制数组来确认查询的数据存不存在,用多个hash函数来计算该查询请求的下标,多个下标记为1,查询时都为1才判断为存在
- 难以做到删除操作,因为同个下标不一定只存一个,然后删除的话会误删其他数据
- 调用相关api,可以设置预计存入的大小和误判率,误判率不能无限小,效率会低,越小占用空间越大,hash函数越多
- 缓存空对象,但是可能会缓存很多空值,设置有效期的话可能导致数据有些不一致
- 布隆过滤器,对查询的参数以hash存储,在查询前做一次过滤,不符合的直接过滤掉
Redis缓存雪崩
- 缓存集中过期或者redis’宕机断网,请求一下子访问到数据库层
- Redis高可用,异地多活
- 限流降级,加锁,保证一个线程查询和写缓存
- 数据预热,在部署前先查询一遍,把大量访问的数据先写到缓存中,分散秒杀时间