首先我们得知道为啥要用Redis
Memcache
Redis
官方给出的是支持10W+QPS(QPS-query per second ,每秒查询次数)
首先知道一个概念
FD:File Descriptor文件描述符
一个打开的文件通过唯一的描述符进行引用,描述符石打开文件的元数据到文件本身的映射
Redis使用的是多路复用IO模型,防止阻塞影响性能
将监控文件是否可读,交给selector,那么线程就可以做点别的事情去了
根据不同的系统,使用不同的多路复用函数,因为所有的系统都会支持select,所以在Redis发现本系统没有更好的可用时会用select
IO多路复用函数:epoll/kqueue/evport/select
首先我们要知道数据量到底有多大,再决定使用什么方式查询
还是刚才的场景,我们用scan指令查询
这样查询不会阻塞,但是可能会出现重复的情况,我们可能需要在应用程序中进行去重
分布式锁需要解决的问题:
SETNX key value :如果key不存在,那么创建并返回
####应用原理
一个线程占用资源时,先SETNX一个值,在执行结束后将值删除
在此期间,别的线程使用相同资源时,先SETNX同样的key,设置无效则证明资源没被释放
EXPIRE key seconds
如果使用资源长期不被释放,那么资源就会一直被占用,我们可以通过设置key过期时间
例如:我们在程序中可以如下设计
long status = redisService.setnx(key,"1");
if(status == 1){
redisService.expire(key,expire);
// 处理单独占用资源的逻辑
}
原子性得不到满足,如上设计方案执行SETNX后挂了,那么过期时间还是没设置啊,这不还是完蛋?
SET key value [EX seconds] [PX milliseconds ] [NX|XX]
SET操作成功返回OK,否则返回nil
使用以下可以保证原子性
long result = redisService.set(key,requestId,SET_IF_NOT_EXIST,SET_WITH_EXPIRE_TIME,EXPIRETIME);
if(result == "OK"){
// 处理单独占用资源的逻辑
}
设置过期时间时,会随机增加毫秒数,防止同一时间过期
使用List进行一个入栈,出栈操作,请忽略中间两步弟弟操作。。
如果pop返回nil,那就说明消费完了,我们程序调用可能需要在此时进行一个延时操作(sleep一会儿再访问)
sleep的方式,总感觉会被面试官锤!!!那么BLPOP闪亮登场
BLPOP key timeout:阻塞至队列有消息或超时
缺点:只能提供给一个消费者
那肯定不得劲~还得升级!
发送者pub发送消息,订阅者可以关注任意数量的频道
在redis.conf文件中,这些是根据不同情况做的不同策略
当备份进程出错,停止写入操作,保护数据
保存备份有两种模式,save和bgsave
当Redis需要备份时,系统fork()创建一个子进程,父进程继续处理客户端的操作,当执行写入时,系统创建一个副本给父进程,子线程备份完毕后,父进程将副本覆盖当前资源
AOF(Append-Only-File)持久化,保存写命令
默认不开启,需要conf文件配置,开启后需要重启
可以执行config set appendonly yes开启增量备份
可以使用RDB-AOF混合持久化方式,4.0版本以后默认此方式
BGSAVE做镜像全量持久化,AOF做增量持久化
现在假设有4个对象:object1-object4,将四个对象hash后映射到环形空间中:
一个cache就是一个redis节点哈
接下来把chche映射到hash空间(基本思想就是讲对象和cache都映射到同一hash数值空间中,并且使用相同的hash算法,可以使用cache的ip地址或者其他因子),假设现在有三个cache:
每个key顺时针往下走,找到的第一个cache节点就是存储位置:
现在移除一个cacheB节点、这时候key4将找不到cache,key4继续使用一致性hash算法运算后算出最新的cacheC,以后存储与读取都将在cacheC上: