redis速度快的原因
基于内存
单线程:worker线程是单线程(工作线程) 但是io线程(读写线程)是多个
基于NIO的多路复用器,在linux系统中是采用epoll形式
redis通信:
1:epoll不会拉取数据,只会告诉你哪个节点有数据传输,然后把信息告诉给worker线程
2:由woker线程去内核中读取对应的客户端传输的数据
3:把数据取回到内存进行计算(set get等操作)
redis串行化
redis是单线程的,所以在并发情况下不需要加锁,它是通过工作线程进行轮询方式处理请求,以串行化的方式处理
redis的弊端
redis是单线程的,只会占用一个cpu核心数,如果cpu核心数很多但对redis性能影响不大,
优化io线程(redis 6.x版本后提供的,非默认行为)
思考:如何统计某个用户一年登陆过的天数?
最简单的统计方式是通过redis的bit
例如:用户(fmj)在第三天登陆了:
setbit fmj 3 1 (将下标为3的bit位设置为1)
用户又在第8天登陆了:
setbit fmj 7 1
用户在第365天登陆了:
setbit fmj 364 1
统计用户一年一共登陆了多少天?
bitcount fmj (统计为1的数量)
AOF持久化日志的流程:
因为redis是单线程,如果实时从内存中写日志会降低性能,所以使用了操作系统的oscache去写入
oscache有个页缓存(pagecache),不停的往pagecache里写入,但是有以下四种:
1:默认5s就会从pagecache持久化到磁盘
2:如果pagecache内存占用超过10%会立即写入磁盘
3:如果超过30%会直接阻塞
4:每秒都会写入磁盘
redis一致性:
redis一般默认弱一致性,但是高版本现在可以通过配置修改为强一致性
弱一致性:主从同步是异步进行的,只需要master返回成功就可以,所以这样可能会丢失数据
强一致性:需要主从同步全部完成后再返回给客户端,但是在同步过程中服务是不可用的,所以等待时间较长
思考:redis做分布式锁靠谱么?
不靠谱,因为redis是弱一致性,可能会存在丢失数据
那为什么还会有人用redis做分布式锁?
那是需要区分具体行业类型,比如金融行业涉及到资金的肯定不可以使用redis做分布式锁,如果其它互联网行业可能关注的地方是响应速度,丢点数据对其影响并不大,所以仍然会使用
redis有什么办法可以保证最终一致性?(此方式暂无人实现)
在主从之间实现一个黑盒技术,且永远不会宕机,由主写入到黑盒中,只要写入成功即可返回给客户端,再由黑盒写道从节点,即使从节点宕机了,等到恢复后也可继续写入,保证了最终一致性。
虽然redis暂未实现该黑盒技术,但是hdfs是实现了这个黑盒技术,下面我们看下它是如何实现的?
hdfs的journalnode就是类似上述的黑盒技术,它是采用集群的结构保证了它的稳定性
redis分布式采用hashSlot算法
每个分片都会维护一个全局的mapping映射表和本地映射表,当客户端请求任意一个分片时会计算出该数据是在哪个槽点上,如果不在当前分片内就会转发到对应的机器上
当redis要扩容时,其它分片只需要平均移动一定数量的槽点到新的机器上,再将该槽点的数据也转移到新的机器上,其它数据则不需要做任何变动