Redis
概念
1、Nosql
2、基于内存的数据库
3、支持集群、分布式、主从同步、一定的事务能力
应用场景
1、作为缓存
2、高速读写的场景
三个角度
1、业务数据命中率高
2、读多写少
3、业务数据大小如何?太大会给缓存带来很大的压力,不要写入缓存
缓存的作用
生产场景下,我们会采取多级缓存,如图片中是四级缓存,从上到下是客户端缓存、网络层缓存、路由层缓存、服务端缓存。服务端缓存又分为本地缓存、分布式缓存(redis).
请求是从上而下来读取缓存的,只有当上层没有缓存到数据,才会向下调用获取。
缓存归根结底的意义,就是使数据更加接近于使用者。
优势
1.性能极高,官方数据Redis能读的速度是110000次/s,写的速度是81000次/s;
2.采用单线程模型,Redis所有操作都是原子性的,同时支持对几个操作全并后的原子性执行;
3.redis不需要依赖操作系统中的类库(memcached需要依赖libevent这样的系统类库)。
比较
和ehcache比较的话,redis是用C实现的,而ehcache是用java。此外redis是独立于应用部署的,而ehcache是和应用共用一个JVM。ehcache比较适合用作单机系统的缓存。
和memcache比较的话,二者都是用C实现的。memcache的缓存数据只支持字符串格式,而redis支持多种数据结构。memcache支持多线程读写,而redis是单线程。memcache不支持持久化,而redis支持。memcache做集群时数据没有复制和同步机制,而redis支持配置集群主从复制。memcache本身并不真正支持分布式,其数据分片的实现需要开发者在客户端借助一致性哈希算法自行实现,而redis官方已经实现了分布式缓存。
数据结构
字符串(String)、哈希(Map)、列表(list)、集合(sets) 和有序集合(sorted sets)。
读逻辑
写逻辑
高速读写
发布订阅
发布者和订阅者都是redis client端,channel是服务器端,发布者将消息发送到某个的频道,订阅了这个频道的订阅者就能接收到这条消息。Redis的这种发布订阅机制与基于主题的发布订阅类似,Channel相当于主题。
持久化
什么是持久化
持久化的目的:
- 防止数据丢失
- 解耦应用和数据。比如,应用退出后,数据会持久化到硬盘上,当应用重新打开时,它会从硬盘上加载先前保存的数据,比如用户信息等。
- 扩展性,能支持用户定义的类型
- 松耦合,不依赖业务逻辑
- 消耗不能太多
- 重用性高
- 至少支持save和load接口
Redis将数据全部保存到内存中,所以有快速读取速度。但如果Redis重启或所在服务器宕机,其存储的数据将全部丢失。
所以,Redis提供了两种持久化方式,即RDB和AOL,这两种方式各有优点。
RDB snapshot数据快照
整个过程如下:
- 首先Redis server会fork一个子进程,这个子进程会和父进程共享相同的内存地址空间
- Redis server会继续处理client的请求,但是如果client对数据有修改,Redis server会新开辟一块内存保存修改后的数据。
- 由于共享的内存没有受到影响,子进程看到的数据依然是fork时刻的数据快照,子进程将共享内存的数据写到一个临时的RDB文件中。
- 当子进程完成内存数据写到临时的RDB文件后,临时文件会替换原来的RDB文件,完成数据备份。
触发方式:
1、save配置
2、客户端给服务端发送SAVE命令或者BGSAVE命令,前者是进行save配置,后者强制立即执行RDB持久化
优点:
1、性能开销小
2、磁盘占用少
缺点
1、每次都是对全量数据进行持久化,两次RDB的间隔至少在5分钟以上。当数据量特别大的时候,这个间隔时间会更长。那么当服务宕机时,可能会丢数分钟的数据。
AOL append only log
AOL会有数据冗余问题,如果client对一个key做了10次写入操作,AOL会写入10条命令到磁盘,但实际只有最后一条命令是有意义的。
故引入AOL重写机制
- 首先Redis会fork一个子进程,这个子进程和父进程共享内存空间
- 父进程除了依然会将新的写入命令添加到原来的aof文件,还会将命令保存到新开辟的内存aof rewrite buf block中。
- 子进程如快照方式,将内存中的全量数据保存到新的aof文件中。然后,再将aof rewrite buf block中的命令追加到新的aof文件结尾。
- 最后,使用最终的aof文件替换旧的aof文件。
建议
1.建议使用mset、mget等批量操作,节约网络I/O;
2.使用事务命令(multi、exec、discard),事务级别相当于read commited,无法看到其他事务未提交的记录改动。可以通过watch key做监控。
3.使用list,如果需要ACK,可用一个sortedSet,每次pop出一个元素按照访问时间当道sortedSet中,消费完删除。
4.对大集合数据删除避免使用del,会造成redis阻塞。思路是先找出一部分删除。