Redis学习笔记
Log
2021-12-07对之前的笔记进行了重构
Redis本质上是一个K/V数据库,这个大家都知道。
参考
狂神说java的redis教程
编程技术宇宙-通俗说redis系列
《redis设计与实现》
redis常用命令
去看这篇博客
Redis常用命令
看这个也行
Redis命令速查——官方文档
# 命令行形式客户端登录
./redis-cli -h host -p port -a passwd
# 清除当前db数据
flushdb
# 清除所有db数据
flushall
redis面试题
这个你真要找网上不要太多:
牛客网的redis面试题1
牛客网的redis面试题2
redis数据结构
Redis有哪些数据类型?除了五大基础类型 STRING HASH SET ZSET LIST
还有hyperloglog bitmap geospatial
# 举例
HSET myhash field1 "Hello"
HGET myhash field1
HSET myhash field2 "Hi" field3 "World"
HGET myhash field2
HGET myhash field3
HGETALL myhash
Hyperloglog和Bitmaps
什么是基数? (基数是不重复的元素,可以接受误差)
Hyperloglog数据结构可以做基数统计的算法(0.81%错误率)
网页的UV(unique vistor)
传统的做法,set保存用户id
但是保存大量用户id的话,就会比较麻烦
PFadd mykey 1 2 3 4 5
PFcount mykey
# 合并为 mykey3
PFmerge mykey3 mykey mykey2
PFcount mykey3
Bitmaps也是一种数据结构
可以用来存每天是否打卡,省内存
setbit sign 0 1
setbit sign 1 0
setbit sign 2 0
setbit sign 3 1
getbit sign 3
# 数二进制位为1的个数
bitcount sign
Zset有序集合 (数据结构)
zadd salary 2500 xiaohong
zadd salary 5000 zhangsan
zadd salary 500 kuangshen
ZRANGEBYSCORE salary -inf +inf withscores
ZRANGEBYSCORE salary +inf -inf
ZREVERANGE #降序排列
zrem salary xiaohong #移除有序集合中指定元素
zcard salary # 获取有序集合中的元素个数
zcount salary 100 200 #获取指定区间中元素数量
应用
排行榜,班级分数排行等等
geospatial 地理位置 (数据结构)
应用
地理定位,附近的人,打车距离计算?
redis复制原理
复制原理
Slave启动后成功连接到master后会发送一个sync同步命令
Master接到命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕后,master将传送整个数据文件给slave,并完成一次完全同步
全量复制:slave服务在接收到数据库文件后,将其存盘并加载到内存中。
增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步
但是只要是重新连接master,一次完全同步(全量复制)将被自动执行
redis哨兵模式
没有哨兵时,master挂了不会选举新的master
哨兵是一个独立的进程,作为进程,通过
常见的就是6个
1.配置哨兵配置文件 sentinel.conf
# sentinel monnitor 被监控的名称 host port 1
# 这里1指 1个哨兵认为这个节点挂了才是真的挂了
2.启动哨兵
./sentinel
如果master节点挂了,这个时候会从从机中按照算法选举出一个新的master节点
主机回来了当然只能当从机了
优点
1.哨兵集群,基于主从复制模式,所有的主从配置优点,它会有
2.主从可以切换,故障可以转移,系统的可用性就会更好
3.哨兵模式就是主从模式的升级,手动到自动,更加健壮
缺点
1.Redis不好在线扩容,集群容量很好一旦到达上限,在线扩容就十分麻烦
2.实现哨兵模式的全部配置其实是很麻烦的,里面有很多选择
# 哨兵配置脚本
#如果有哨兵集群,每个哨兵要指定端口
#每个哨兵有密码
#通知脚本(sh脚本)
redis发布/订阅
Redis 发布订阅有队列的
设计模式----消息通信模式,订阅发布模式,
观察者模式没有队列的,,,,
Consumer-消息通知-Producer
1.官网下载redis-stable并编译
wget http://download.redis.io/redis-stable.tar.gz
tar -xzvf redis-stable.tar.gz
cd redis-stable
make
cp src/redis-cli /usr/local/bin/
2.测试
redis-cli -h host -p port -a password
# 客户端连接,方便输入命令
redis-cli -p 6379
ping #测试联通
#publish channel message
publish yhm138 "hello"
subscribe yhm138
Pub/Sub从字面上理解就是发布与订阅,在Redis中,你可以设定对一个key进行消息发布及消息订阅,当一个key的值进行了消息发布后,所有订阅它的客户端都会收到对应的消息,这一切最明显的用法就是做实时消息系统,比如简单的即时聊天,群聊等等。
复杂的场景,可以使用专业的消息中间件来做 RabbitMQ、Kafka、RocketMQ
持久化之AOF操作和RDB操作
AOF append only file
只记录写的命令,形成一个文件
#如果这个aof文件有错位,这时候redis是起不来的,我们需要修复
redis-check-aof --fix appednonly.aof
aof的优点:
1.每一次修改都同步,文件的完整会更加好
2.每秒同步一次,可能会丢失一秒的数据
3.从不同步,效率最高的
缺点:
1.相对于数据文件来说,aof远远大于rdb,恢复的速度要比rdb慢!!!
2.aof的运行效率比rdb慢(涉及io)
redis默认是rdb持久化,aof需要手动开启
RDB ,Redis DB 简写?
缓存穿透/缓存击穿/缓存雪崩
缓存穿透
解决方案
布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,从而避免了对底层缓存的查询压力
但是这种方法会存在2个问题:
1.如果空值能被存储起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键
2.即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响。
缓存击穿 (量太大,缓存过期)
解决方案
设置热点数据永不过期。
分布式锁。加锁,保证一次一个线程进去
缓存雪崩 (缓存中key大量失效,大量请求打到MySQL上)
解决方案
Redis高可用。多增设几台Redis。异地多活
停掉一些服务
数据预热,把可能的热点数据提前加载到Redis上
redis是单线程,为什么这么快?
1、Redis 单线程到底指什么?. 没错,大家所熟知的 Redis 确实是单线程模型,指的是执行 Redis 命令的核心模块是单线程的,而不是整个 Redis 实例就一个线程,Redis 其他模块还有各自模块的线程的。. Redis基于Reactor模式开发了网络事件处理器,这个处理器被称为文件事件处理器。. 它的组成结构为4部分:多个套接字、IO多路复用程序、文件事件分派器、事件处理器。. 因为文件事件分派器队列的消费是单线程的,所以Redis才叫单线程模型。.
redis实现乐观锁
悲观锁:无论做什么都会加锁
乐观锁:更新数据的时候判断一下,在此期间是否有人修改过这个数据
set money 100
set out 0
watch money
multi
decrby money 20
incrby out 20
exec (如果在exec前money被另一个线程修改了,那么事务执行失败)
使用redis的watch可以实现乐观锁
redis的基本事务操作
Redis单条命令式保存原子性的,但是事务不保证原子性
Redis事务没有隔离级别的概念
Redis的事务:
开启事务(multi)
命令入队
执行事务(exec)
discard (放弃事务,入队的命令都没有执行)
编译型异常 -》》》 所有的命令都不会执行
运行异常 -》》》 其他的命令(前面的和后面的)是可以执行的
各种语言连接redis
jedis
Jedis干什么用? 拿Java操作Redis
Python的redis模块
redis实现里的一些细节
RESP协议
Redis把创造出来的这种协议称为RESP (REdis Serialization Protocol)协议,它工作在 TCP 协议的上层,作为我和客户端之间进行通讯的标准形式。例如
随手记
Redis是Remote Dictionary Server 远程数据服务器的缩写
由一位意大利人开发,
内存缓存数据库,
使用C编写,
数据模型为key-value
支持丰富的数据类型
默认端口6379
Redis默认是master
slaveof ip port
#认定一个redis为master
info replication
#查看主从信息
slaveof no one
# 自己成为主节点(手动)
主机可以写,从机只能读。主机中的所有信息和数据,从机都会读取
性能测试和压力测试的区别:
性能测试是为了获得系统在某种特定的条件下(包括特定的负载条件下)的性能指标数据,而负载测试、压力测试是为了发现软件系统中所存在的问题,包括性能瓶颈、内存泄漏等。