1.Redis主从模式、哨兵模式
在前一章持久化文章【AOF和RDB【Redis持久化篇】 中,我们知道了Redis是内存数据库,可以通过持久化保存RDB和AOF的方式,将数据持久化到磁盘。如果,这个机器或磁盘出现问题,数据还是没有了,怎么办呢?
在前一章持久化文章【AOF和RDB【Redis持久化篇】 中,我们知道了Redis是内存数据库,可以通过持久化保存RDB和AOF的方式,将数据持久化到磁盘。如果,这个机器或磁盘出现问题,数据还是没有了,怎么办呢?
MULTI:标记事务开始,后续命令会排队等待执行。 EXEC:提交并执行在事务中的所有命令。 DISCARD:取消事务,丢弃所有队列中的命令。 WATCH:监视一个或多个键,在事务执行前,如果这些键被修改,事务会被中断。
消息队列
消息队列是什么?
消息队列有先入先出的特征,一般用于异步流程、消息分发、流量削峰等问题,可以通过消息队列实现高性能、高可用、高扩展的架构。
锁通常用来控制共享资源,比如一个进程内有多个线程竞争一个数据的使用权限,解决方式之一就是加锁。分布式锁,就是在分布式场景下的锁,比如多台不同机器上的进程,去竞争同一项资源,就是分布式锁。
一个优秀的分布式锁需要具有互斥性、抗死锁性、对称性、可靠性。
接下来,主要探究Redis是怎么实现这个分布式锁。Go!
Redis由于性能高效,通常可以做数据库存储的缓存。一般而言,缓存分为服务端缓存和客户端缓存。缓存有以下三种模式:
缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求。由于缓存时不命中后查询DB时被动写入的,并且在DB查不到数据则不写入缓存,这就会导致这个请求每次都要到存储层查询,缓存毫无意义了。在流量大时,DB也可能会挂掉。
Redis是跑在内存里的,当程序重启或者服务器崩溃,数据就会丢失,如果业务场景希望重启之后数据还在,就需要持久化,即把数据保存到可永久保存的存储设备中。
那要怎么存储呢?
Redis提供了两种方式:
Redis是内存存储,都是以键值对形式存放在内存。其实就是存放到RedisDB中名叫dict的HASHTABLE中。
/* Redis数据库结构体 */
typedef struct redisDb {
// 数据库键空间,存放着所有的键值对(键为key,值为相应的类型对象)
dict *dict;
// 键的过期时间
dict *expires;
// 处于阻塞状态的键和相应的client(主要用于List类型的阻塞操作)
dict *blocking_keys;
// 准备好数据可以解除阻塞状态的键和相应的client
dict *ready_keys;
// 被watch命令监控的key和相应client
dict *watched_keys;
// 数据库ID标识
int id;
// 数据库内所有键的平均TTL(生存时间)
long long avg_ttl;
} redisDb;
跳表是Redis有序集合ZSet底层的数据结构,跳表在ZSET中尤其重要。 跳表的本质还是链表,只是在普通链表的基础上,增加了多级的索引,通过索引可以一次实现多个节点的跳跃,提高性能。
跳表的结构
标准的跳表(Redis不是使用标准的跳表)有以下限制:
Redis Hash是一个field、value都为string的hash表,存储在Redis的内存中。
适用于O(1)时间字典查找某个field对应数据的场景,比如任务信息的配置,就可以任务类型为field,任务配置参数为value。
Redis的Set是一个不重复、无序的字符串集合。
适用于无序集合场景,比如某个用户关注了哪些公众号,这些信息就可以放进一个集合,Set提供了查交集、并集的功能,可以很方便地实现共同关注的功能。
String就是字符串,最大为512MB。
适用存储字节数据、文本数据、序列化后的对象数据等。
缓存场景,Value存Json字符串等信息。
计数场景,因为Redis处理命令是单线程,所以执行命令的过程时原子的。因此String数据类型适合计数场景,比如计算访问次数、点赞、转发、库存数量等。
创建、查询、更新、删除。