redis 学习笔记
CAP理论
一个分布式系统不可能同时很好的满足一致性,可用性,和分区容错性
一个分布式系统只能同时较好地满足两个
Consistency(强一致性)
在分布式系统中的所有数据备份,在同一时刻是否同样的值。
Availability (可用性)
在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。
Partition tolerance (分区容错性)
以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。
CA
单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强
例如:Oracle
CP
满足一致性,分区容错的系统
例如:Redis
AP
满足可用性,分区容忍性的系统,通常对一致性要求不高
例如:大多数网站架构
BASE
BASE 是为了解决关系性数据库的强一致性引起的问题而引起的可用性降低而提出的解决方案
通过让系统放松对某一时刻数据一致性的要求来换取系统整体伸缩性和性能表现上的改观
大型系统在高并发的情况下往往会有极高的性能要求,不拿使用分布式事务来完成这些目标
Basically Available
基本可用
Soft state
软状态,是指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时。
Eventually consistent
最终一致,强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。
安装redis
下载redis
解压,cd到目录下,执行
make
如果出错,需要更新gcc版本
更改配置
可以复制redis.conf
文件到一个新的文件夹下,然后进行vim编辑
# By default Redis does not run as a daemon. Use 'yes' if you need it.
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
daemonize no
更改后台服务启动
cd src
./redis-server 配置文件路径
# 启动client测试
./redis-cli
redis五大数据类型
键(key)
字符串(String)
string类型是二进制安全的,可以是任何类型
string是redis的最基本的数据类型,最多支持512m
列表(List)
list是一个简单的字符串列表,按照插入方式排序,它的底层是一个链表
单值多value
集合 (Set)
无序无重复
哈希 (Hash)
类似于java中的表
有序集合 (Zset)
排序的集合,在set上会关联一个double类型的分数
redis 配置文件
include
可以包含一个或多个配置文件
include /path/to/local.conf
general
- tcp-backlog: 连接队列,高并发的情况下需要一个高backlog来避免慢客户端的访问问题
- port:端口
- timeout:超时时间
- tcp-keepalive:检测是否中断
- loglevel:日志级别
- database:数据库数量
snapshot
保存为一个db在磁盘上
save <second> <changes>
second
秒内改changes
次就会触发备份
默认的是
- 15分钟改1次
- 5分钟改10次
- 1分钟改1w次
-
stop-write-on-bgsave-error 后台出错前台停止写操作
-
rdbcompression 压缩
-
rdbcchecksum:存储后进行CRC64进行数据校验
replication复制
security
redis可以设置密码
config set requirepass "123456"
# 设置完需要登录
auth 123456
limit
- maxclient
- maxmenory
- maxmemory-policy
- volatile-lru: 用LRU算法移除key,只对设置了过期时间的键
- allkeys-lru:使用lRU算法移除key
- volatile-random: 在国企的集合中移除随机的key,只对设置了过期时间的键
- allkeys-random:移除随机的key
- volatile-tll:移除ttl最小的key
- noeviction:不进行移除
- maxmemory-samples
持久化
RDB
Redis DataBase
在指定的时间间隔内的数据集快照写入磁盘
redis和单独创建一个子进程来进行持久化,首先将数据写入一个临时文件中,持久化过程都结束了,再进行临时文件到替换
整个过程中,主进程是不进行IO操作的,保证了性能
如果进行大规模的数据恢复且对数据恢复的完整性不是那么敏感,RDB比较高效
RDB的缺点是最后一次持久化后的数据可能丢失
Fork
Fork的作用是复制一个与当前进程一样的进程,新进程的所有数据与原进程一致
恢复数据
自动读回
AOF
Append Only FIle
以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来
只许追加文件,但不可以改写文件,reids启动之初就会读取该文件重新构建数据,redis重启以日志的指令从前到后都执行一次完成恢复工作
开启AOF
appendonly yes
开启后每执行一个命令都会在指定目录下生成aof文件
如果dump.rdb和aop共存,会默认读取aof
修复AOF
Redis-check-aof --fix
AOF的具体配置
- appendonly
- appendfilebname
- appendfsync
- always:同步持久化,每次变更会立即记录到磁盘
- everysec:出场默认,每秒记录
- no
- no-appendfsync-on-write:重写时是否可以使用appendfsync,默认no,保证数据安全性
rewrite
重写
AOF采用文件追加的方式,文件会越来越大为避免出现此种情况,新增了重写机制,当AOF文件超过所设的阈值时,redis会对AOF文件的内容压缩
redis会记录上次重写时AOF的大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发
- auto-aof-rewrite-percentage 100
- auto-aof-rewrite-min-size 64
RDB和AOF对比
官网建议同时开启两种持久化方式
RDB
- 如果数据敏感性低用RDB
- 保存的文件比较小
AOF
- 数据保存比较完整
- 保存的文件比较大
- 性能影响比较大
Redis事务
可以一次性执行多个命令,本质是一组命令的集合
一个事务的所有命令都会被序列号,串行地执行命令
redis 是部分支持事务的
开始一个事务
以如下语句开始的所有事情都会被作为一个事务
MULTI
放弃一个事务
书写如下语句放弃一个事务
DISCARD
事务的特性
一个事中的语句是错的,其他事务也不执行
其他事务不执行(类似编译错误)
但是如果是执行失败,但是其他都正常,其他还是正常执行
(类似于Java中的运行时异常)
watch
乐观锁 & 悲观锁 & CAS
行锁 & 表锁
- 表锁:对整张表加锁,整张表都被锁了会导致性能问题
- 并发性差
- 一致性好
- 行锁:对行加锁
- 并发性好
悲观锁
我认为一定会有人改,对整张表进行加锁
乐观锁
我认为没人会改我的数据
可以加一个版本号,如果有人要改记录必须修改版本号,如果提交版本大于等于当前版本才能更新
在实际应用中用乐观锁非常多
CAS
设计场景
搭建转账场景
# 设置实验数据
set account1 100
set account2 800
# 下面为客户端一的代码
watch account2
multi
此时打开另外一个redis-cli
执行以下代码
set account2 900
再继续写客户端一的代码
decrby account2 200
incrby account1 200
exec
此时发现执行是失败的,因为值已经被修改了
现在查看值是另外一个客户端修改后的值
小结
watch的指令类似于乐观锁,事务提交时,如果key的值已经被别的客户端修改,比如说某个list已被别的客户端push/pop过了,整个事务队列都不会被执行
通过watch命令在事务执行前监控了多个keys,倘若在watch之后有任何key发生改变
,EXEC命令的所有事务都会被抛弃,同时返回Nullmulti-bulk
通知调用者事务失败
三个特性
- 单独的隔离操作,事务的执行是有顺序的
- 没有事务隔离级别的概念
- 不保证原子性,正确的命令也会正确执行
redis的发布和订阅
是一种进程间的消息通信模式:发送者发送消息,订阅者接收消息
- subsctibe
- publish