Memcache:代码层次类似于Hash。
Redis:
FD:File Descriptor,文件描述符
一个打开的文件通过唯一的描述符进行引用,该描述符是打开文件额元数据到文件本身的映射。
传统的阻塞I/O模型:
前面的没有处理完成,后面的则进行阻塞。等待前面的读写完成以后,才会执行后面的方法。
多路I/O复用模型
Select系统调用
同时监视多个文件是否可读可写,系统把读写交给Selector,自己执行别的操作。
Redis采用的IO多路复用函数:epoll/kqueue/export/select?
String可以存储任何类型,JPG,以及序列化的内容。
Redis是原子性的。
hmset lilei name "LiLei" age 25 title"Senior"
hget lilei age
hget lilei title
hset lilei title "Pricipal"
lpush myList aaa
lpush myList bbb
lpush myList ccc
lrange myList 0 10 #从左往后取,"ccc","bbb","aaa"
sadd myset 111
sadd myset 222
smembers myset
"111"
"222"
元素不可以重复,但是分数是可以重复的。
zadd myzset 3 aaa
zadd myzset 2 bbb
zrangbyscore myzset 0 10//分数越小,越靠前
"bbb"
"aaa"
Redis底层数据类型基础
摸清数据规模,即问清楚边界。
KEYS pattern:査找所有符合给定模式 pattern的key
keys一次返回所有的key,对性能消耗很严重。key过大,系统会卡顿。
dbsize //查看redis中数量
keys k1* //查找以k1开头key的数据
SCAN
SCAN cursor [MATCH pattern] [COUNT] count
SCAN 0 match k1* count 10
0:开始的游标位置
k1*:以k1开头的key
10:建议返回数量10(只是建议,不一定为10)
"1330812"
"k183843"
"k183831"
会返回cursor的值(1330812),用于下次的查询
分布式锁需要解决的问题
SENTX Key value:如果key不存在,则创建并复制
setnx locknx test
加入key(locknx)。如果存在返回0(设置失败),不存在返回1(设置成功)
如何解决SENTNX长期有效的问题
EXPIRE key seconds
设置key的生存时间,当key过期时(生存时间为0),会被自动删除。
expire locknx 2
设置locknx过期时间为2秒
一个设置分布式锁的代码,错误的,2个原子性操作,分布执行,整体不一定为原子性。
RedisService redisService= SpringUtils.getBean(RedisService class);
long status=redisService.setnx(key,1"):
if(status= 1)[
redisService expire(key,expire);
//执行独占资源逻辑
doocuppiedwork()
}
Set key value[EX seconds][PX milliseconds][NX|XX]
# 添加lock-1234 数据,过期时间10s。NX不存在,才进行操作
set lock 1234 ex 10 nx
集中过期,由于清除大量的key很耗时,会出现短暂的卡顿现象
使用List作为队列,Rpush生产消息,Lpop消费消息。
BLPOP key[key…]timeout:阻塞直到队列有新消息或者超时
rpush testList aaa
rpop testList
"aaa"
blpop testList 30 //等待30秒,等待添加数据
pub/sub:主题订阅者模式
subscribe myTopic //订阅myTopic频道
publish myTopic "Hello" //向频道myTopic发布消息
消息的发布是无状态的,无法保证可达,(发布时不在线,则无法接收)
RDB(快照)持久化:保存某个时间点的全量数据快照。
vim redis.conf
save 900 1
save 300 10 //300秒内有10条写入,就触发一次快照,没有的话
save 60 10000 //
//备份进程失败的时候,主线程会停止接受新的写入操作,保证持久化数据一致性,(一般默认开启的)
stop-writes-on-bgsave-error yes
//RDB文件压缩相关,在备份的时候,将文件压缩才进行保存(默认no)
rdbcompression yes
//禁用RDB的配置
save ""
手动进行RDB备份命令
//返回上次RDB持久化的时间
lastsave
//阻塞主线程,进行持久化
save
//开辟子线程,进行持久化。
bgsave
自动化触发RDB持久化的方式
BGSAVE原理
系统调用fork( ):创建进程,实现了Copy-on-Write(写实复制)(COW)
如果有多个调用者同时要求相同资源(如内存或磁盘上的数据存储),他们会共同获取相同的指针指向相同的资源,直到某个调用者试图修改资源的内容时,系统才会真正复制份专用副本给该调用者,而其他调用者所见到的最初的资源仍然保持不变。
RDB持久化缺点:
appendonly no //默认关闭AOF持久化方式
appendfilename "appendonly.aof //AOF持久化文件
//AOF持久化策略
appendtsync always //及时写入(有更新就写入)
appendtsync everysec //每秒写入
appendtsync no //写入由操作系统决定(一般是缓存区填满以后)
日志重写解决AOF文件大小不断增大的问题,原理如下:
# AOF文件大小较上次重写超过100%时进行重写
auto-aof-rewrite-percentage 100
# aof文件大小超过64m时重写
auto-aof-rewrite-min-size 64mb
Redis数据的恢复
RDB和AOF文件共存情况下的恢复流程
RDB和AOF的优缺点:
RDB-AOF混合持久化方式(4.0)(默认配置)
主从同步原理
Master:进行写操作
Sync:进行读操作
最后一致性。
全量同步过程:
增量同步过程:
Redis Sentinel(哨兵机制)
Redis官方提供的集群管理工具,监控M-S集群,发现Master宕机后,能进行切换。
解决主从同步 Master宕机后的主从切换问题:
将一个S提升为M,通过流言协议来接收主服务器是否下线通知,通过投票协议执行故障迁移,哪台服务器作为新的主服务器。
流言协议(Gossip)
在杂乱无章中寻求一致
如何从海量数据里快速找到所需?
一致性哈希算法:
假定Node C宕机:
Object C本来应该存到Node C,但是Node C宕机,则会存到Node D中,只需要重新定位环中的一小部分问题,最小化的有损服务。
假定新增节点(Node F)
只要其周边的一个回定位到新增的,只会影响新增节点与前一节点之间的数据。
有较好的容错性和扩展性。
遇到的问题:Hash环的数据倾斜问题
数据运算后与B节点很近,则会存储到节点B中,造成数据倾斜。把服务器撑爆。
解决:引入虚拟节点解决数据倾斜的问题
只有2个实际节点,虚拟出6个虚拟节点
为了避免单点故障,我们需要将数据复制多份部署在多台不同的服务器上,即使有一台服务器出现故障其他服务器依然可以继续提供服务。
这就要求当一台服务器上的数据更新后,自动将更新的数据同步到其他服务器上,这时候就用到了Redis的主从复制。