a).mysql是关系型数据库,而redis是NOSQL,非关系型数据库。mysql将数据持久化到硬盘,读取数据慢,而redis数据先存储在缓存中,读取速度快,但是保存时间有限,最后按需要可以选择持久化到硬盘。
b).mysql作为持久化数据库,每次访问都要在硬盘上进行I/O操作。频繁访问数据库会在反复连接数据库上花费大量时间。redis则会在缓存区存储大量频繁访问的数据,当浏览器访问数据的时候,先访问缓存,如果访问不到再进入数据库.
a) 字符串类型 String 添加操作:set
b) 哈希对象 hash 添加操作: hset
c). 列表对象 list 添加操作: lpush
d). 集合对象 set 添加操作:sadd
e). 有序集合对象 sorted set 添加操作: zadd
(其他操作略)
拉链法。这个问题可以考虑到另一个问题,HashMap是如何解决key冲突的,同样也是采用拉链地址法。如果被问到解决key值冲突还有什么方法?一般来说解决key值冲突的方法有俩种,一种是开放地址法,另一种就是拉链法。
首先要明白什么是持久化?上面第一个问题已经阐述过了,简单来说,类似于MySQL这种直接将数据存到硬盘的方式就是持久化。但是Redis又不能照搬照抄SQL的存储方法,最大的原因也是讲过的——NoSQL,也就意味着没有类似于B+树的操作。
第一种方式 RDB持久化策略。也是redis的默认方法。先将数据存储到内存,当数据累计到某种设定的阈值后会触发一次DUMP 操作,将变化的数据存进RDB文件。一旦 Redis 异常退出,就会丢失最后一次快照以后更改的所有数据
第二种方式:开启AOF持久化策略 先将数据存储到内存。开启 AOF 持久化后每执行一条会更改 Redis 中的数据的命令,Redis 就会将该命令写入硬盘中的 AOF 文件.AOF文件不存储数据,储存的是执行的命令。 AOF最关键的配置就是关于调用fsync追加日志文件的频率,有两种预设频率,always每次记录进来都添加,everysecond 每秒添加一次。(fsync函数的作用就是将数据从内存写入硬盘)。
由于AOF和RDB存储的文件内容并不相同,RDB存储的是真实的,存进去的数据,AOF存储的是大量操作数据的指令,这种指令一旦增多,就会必然使得AOF文件扩大,所以会引发一种新的机制:Rewrite。所谓Rewrite就是将日志文件中的所有数据都重新写到另外一个新的日志文件中,但是不同的是,对于老日志文件中对于Key的多次操作,只保留最终的值的那次操作记录到日志文件中,从而缩小日志文件的大小。
auto-aof-rewrite-percentage 100 (当前写入日志文件的大小占到初始日志文件大小的某个百分比时触发Rewrite)。 |
---|
auto-aof-rewrite-min-size 10mb (本次Rewrite最小的写入数据量)。 |
如何设置redis的过期时间?最简单的就是使用
expire key second,当然还有各种其他方式,比如
pexpire key milliseconds等等,redis查看过期时间的语法也很简单,ttl key就可以看到还剩多长时间。
如何去去删除一个过期的key,最容易想到的就是给每一个key都创建定时器,时间一到就自动删除。这个方法是不靠谱的,虽然它能保证每个过期的key都能被尽快删除,但是创建定时器本身就是一个消耗大量资源的工程,所以并不可取。
redis内置的策略叫做惰性删除,也叫“被动删除”。
key过期的时候不删除,每次从数据库获取key的时候去检查是否过期,若过期,则删除,返回null。
这个方法是可取的,但是必然存在另外一个问题,使用的时候判断是否过期再删除,万一我不使用呢?
若大量的key在超出超时时间后,很久一段时间内,都没有被获取过,那么可能发生内存泄露
内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory; 内存泄露
memoryleak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。内存溢出是堆空间存储内存不够,GC后仍然没有足够的内存来存储新的对象,产生OOM错误。
内存泄露是对象虽然是无用的,但是它仍然是GCroot对象可关联的路径,没有办法GC回收,但是一旦积累过多就会造成OOM.
这时候还是需要redis去主动检索,所以需要使用另一种策略,
定期删除。,又被称作主动删除。
每隔一段时间执行一次删除(在redis.conf配置文件设置hz,1s刷新的频率)过期key操作
第一、配置redis.conf 的hz选项,默认为10 (即1秒执行10次,100ms一次,值越大说明刷新频率越快,最Redis性能损耗也越大)
第二、配置redis.conf的maxmemory最大值,当已用内存超过maxmemory限定时,就会触发主动清理策略。主动清理策略不同于主动删除,要尽量避免触发主动清理。
*
同时,redis 的过期策略对于持久化并没有影响。如果使用RDB,在持久化key之前就会检测是否过期,过期的key不会被存进文件中,同时从RDB恢复到内存数据库时也会检测一次是否过期。
如果使用AOF,由于存储的都是指令,如果key过期,程序会向AOF中追加del指令。在触发Rewrite的时候,会判断key是否过期,过期的key指令不会重写到AOF文件中。
redis的集群有多个,但是性能最强大的是官方的redis-cluster。
1.使用去中心化化思想, 使用hash slot方式 将16348个hash slot 覆盖到所有节点上 对于存储的每个key值 使用CRC16(KEY)&16348=slot 得到他对应的hash slot 并在访问key时就去找他的hash slot在哪一个节点上 然后由当前访问节点从实际被分配了这个hash slot的节点去取数据。
2.投票容错。通过投票容错机制判断节点是否还在工作中。Redis集群中每个节点都会按时向其他节点发送”心跳包”。当有一个节点不响应时,则判断该节点故障。要求是超过半数的投票不响应。
3.为了解决节点master失效fail的问题,可以使用主从复制策略。
什么时候整个集群不可用(cluster_state:fail)?
如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成集群的slot映射[0-16383]不完整时进入fail状态.
如果集群超过半数以上master挂掉,无论是否有slave(从),集群进入fail状态.
Tips:A,B,C三个节点中存储的数据时不一致的,三个节点集成在一起才是完成数据。但是主服务器A 和从服务器a中存储的数据时一直的。
架构细节:
(1)所有的 redis 节点彼此互联(PING-PONG 机制),内部使用二进制协议优化传输速度和带
宽.
(2)节点的 fail 是通过集群中超过半数的节点检测失效时才生效.
(3)客户端与 redis 节点直连,不需要中间 proxy 层.客户端不需要连接集群所有节点,连接集群
中任何一个可用节点即可
redis是单线程的!
redis 核心就是 如果我的数据全都在内存里,我单线程的去操作 就是效率最高的,为什么呢,因为多线程的本质就是 CPU 模拟出来多个线程的情况,这种模拟出来的情况就有一个代价,就是上下文的切换,对于一个内存的系统来说,它没有上下文的切换就是效率最高的。redis 用 单个CPU 绑定一块内存的数据,然后针对这块内存的数据进行多次读写的时候,都是在一个CPU上完成的,所以它是单线程处理这个事。在内存的情况下,这个方案就是最佳方案。
什么时候用多线程的方案呢?
答案是:下层的存储等慢速的情况。比如磁盘