Redis主从复制可以根据是否是全量分为全量同步和增量同步。以下对其相应的同步过程及原理做下简要说明。 增量同步 Redis增量同步主要指Slave完成初始化后开始正常工作时,Master发生的写操作同步到Slave的过程。通常情况下, Master每执行一个写命令就会向Slave发送相同的写命令,然后Slave接收并执行。 全量同步 Redis的全量同步过程主要分三个阶段: 同步快照阶段:Master创建并发送快照给Slave,Slave载入并解析快照。Master同时将此阶段所产生的新的写命令存储到缓冲区。 同步写缓冲阶段:Master向Slave同步存储在缓冲区的写操作命令。 同步增量阶段:Master向Slave同步写操作命令。
纯内存操作。 核心是基于非阻塞的 IO 多路复用机制。 C 语言实现,一般来说,C 语言实现的程序“距离”操作系统更近,执行速度相对会更快。 单线程反而避免了多线程的频繁上下文切换问题,预防了多线程可能产生的竞争问题。
持久化RDB(redis database)和AOF(append only file)的区别 RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件, 写入成功后,再替换之前的文件,用二进制压缩存储。 RDB持久化保存键空间的所有键值对(包括过期字典中的数据),并以二进制 形式保存,符合rdb文件规范,根据不同数据类型会有不同处理。 AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细 的操作记录。AOF持久化保存redis服务器所执行的所有写命令来记录数据库状态,在写入之前命令存储在aof_buf缓冲区。 持久化RDB和AOF的优缺点: RDB存在哪些优势呢? (1) 一旦采用该方式,那么你的整个Redis数据库将只包含一个文件,这对于文件备份而言是非常完美的。比如,你可能打算每个小时 归档一次最近24小时的数据,同时还要每天归档一次最近30天的数据。通过这样的备份策略,一旦系统出现灾难性故障,我们可以非常 容易的进行恢复。 (2) 对于灾难恢复而言,RDB是非常不错的选择。因为我们可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。 (3) 性能最大化。对于Redis的服务进程而言,在开始持久化时,它唯一需要做的只是fork出子进程,之后再由子进程完成这些持久化 的工作,这样就可以极大的避免服务进程执行IO操作了。 (4) 相比于AOF机制,如果数据集很大,RDB的启动效率会更高。 RDB又存在哪些劣势呢? (1) 如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现 宕机现象,此前没有来得及写入磁盘的数据都将丢失。 (2). 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒, 甚至是1秒钟。 AOF的优势有哪些呢? (1) 该机制可以带来更高的数据安全性,即数据持久性。Redis中提供了3种同步策略,即每秒同步、每个命令同步和不同步。事实上, 每秒同步也是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每个命令 同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中。可以预见,这种方式在效率上是最低的。至于无 同步,由操作系统决定任何将缓冲区里面的命令写入磁盘里面,在这种模式写,服务器遭遇意外停机时,丢失命令的数据是不确定的 (2) 由于该机制对日志文件的写入操作采用的是append模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的 内容。然而如果我们本次操作只是写入了一半数据就出现了系统崩溃问题,不用担心,在Redis下一次启动之前,我们可以通过redis- check-aof工具来帮助我们解决数据一致性的问题。 (3) 如果日志过大,Redis可以自动启用rewrite机制。主要是为了解决aof文件不断增长减少重复键读写操作的日志, 通过定时触发, 重新根据实际内存键值情况写入新的aof文件, 再进新旧替换文件,实现aof文件最小化。 (4) AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上,我们也可以通过该文件完成数据的重建。 AOF的劣势有哪些呢? (1) 对于相同数量的数据集而言,AOF文件通常要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。 (2) 根据同步策略的不同,AOF在运行效率上往往会慢于RDB。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB 一样高效。 二者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来 换取更高的性能,待手动运行save的时候,再做备份(rdb)。rdb这个就更有些 eventually consistent的意思了。不过生产环境 其实更多都是二者结合使用的。
1.消息队列。2.排行榜。3.最新列表。
继承LinkHashMap并重写removeEldestEntry方法。
使用缓存,最主要的目的是提升系统的响应速度和对高负载的承受能力。
redis,memcached都有用过。
RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。
AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。
二者优缺点
RDB存在哪些优势呢?
1). 一旦采用该方式,那么你的整个Redis数据库将只包含一个文件,这对于文件备份而言是非常完美的。比如,你可能打算每个小时归档一次最近24小时的数据,同时还要每天归档一次最近30天的数据。通过这样的备份策略,一旦系统出现灾难性故障,我们可以非常容易的进行恢复。
2). 对于灾难恢复而言,RDB是非常不错的选择。因为我们可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。
3). 性能最大化。对于Redis的服务进程而言,在开始持久化时,它唯一需要做的只是fork出子进程,之后再由子进程完成这些持久化的工作,这样就可以极大的避免服务进程执行IO操作了。
4). 相比于AOF机制,如果数据集很大,RDB的启动效率会更高。
RDB又存在哪些劣势呢?
1). 如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。
2). 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟。
AOF的优势有哪些呢?
1). 该机制可以带来更高的数据安全性,即数据持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中。可以预见,这种方式在效率上是最低的。至于无同步,无需多言,我想大家都能正确的理解它。
2). 由于该机制对日志文件的写入操作采用的是append模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容。然而如果我们本次操作只是写入了一半数据就出现了系统崩溃问题,不用担心,在Redis下一次启动之前,我们可以通过redis-check-aof工具来帮助我们解决数据一致性的问题。
3). 如果日志过大,Redis可以自动启用rewrite机制。即Redis以append模式不断的将修改数据写入到老的磁盘文件中,同时Redis还会创建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行rewrite切换时可以更好的保证数据安全性。
4). AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上,我们也可以通过该文件完成数据的重建。
AOF的劣势有哪些呢?
1). 对于相同数量的数据集而言,AOF文件通常要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
2). 根据同步策略的不同,AOF在运行效率上往往会慢于RDB。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB一样高效。
二者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。rdb这个就更有些 eventually consistent的意思了。
先添加删除节点,再移动槽位 reshard,利用一致性哈希的原理保证移动槽位的时候不影响其他节点。
FIFO:First In First Out,先进先出。判断被存储的时间,离目前最远的数据优先被淘汰。
LRU:Least Recently Used,最近最少使用。判断最近被使用的时间,目前最远的数据优先被淘汰。
LFU:Least Frequently Used,最不经常使用。在一段时间内,数据被使用次数最少的,优先被淘汰。
导致缓存穿透的原因:
https://www.cnblogs.com/telwanggs/p/10856157.html
即redis的缓存每命中一次,就给命中的缓存增加一定ttl(过期时间)(根据具体情况来设定, 比如10分钟).
一段时间后, 热数据的ttl都会较大, 不会自动失效, 而冷数据基本上过了设定的ttl就马上失效了.
使用userId为key
ttl为一小时的数字值表示登录次数
超过5次即限制
设置过期时间 加 双删
一、缓存穿透
概念:缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。
解决方案:
二、缓存雪崩
概念:指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。侧重很多的缓存数据都失效了。
解决方案:
三、缓存击穿
概念:
指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
解决方案:
list是双向链表。列表常用来作为异步队列使用
通过使用rpush、rpop、lpush、lpop四条指令,在链表的表头和表尾追加或移除元素,可以将链表作为队列或堆栈使用;
监视这个挂了的主节点的所有Sentinel都有被选举为领头的资格 每进行一次选举,不论是否成功,配置纪元+1,配置纪元就是个计数器 每个Sentinel在每个配置纪元中有且仅有一次选举机会,一旦选好了该节点认为的主节点,在这个纪元内,不可以再更改 每个发现服务器挂了的Sentinel都会配置纪元+1并投自己一票,接着发消息要求其他Sentinel设置自己为领头人1,每个Sentinel都想成为领头的 每个Sentinel会将最先发来请求领头的节点设为自己的领头节点并发送回复,谁先来我选谁 当源Sentinel收到回复,并且回复中的配置纪元和自己的一致且领头Id是自己的Sentinel Id时,表明目标Sentinel已经将自己设为领头 在一个配置纪元内,当某个Sentinel收到半数以上的同意回复时,它就是领头的了 如果在给定时间内,没有被成功选举的Sentinel,那么过段时间发起新的选举 选举领头Sentinel的过程和规则大概就如上所述,需要注意的是只有集群出现节点挂了才需要选举出领头Sentinel,平时每个Sentinel还是平等身份~ 这里的选举其实是raft算法的一个应用.
https://blog.csdn.net/qq_39399966/article/details/101211939
https://blog.csdn.net/achuo/article/details/80600170集中式:容量,并发瓶颈,但一致性有保证。
分布式:提升容量,并发能力,但会有一致性问题。
redis使用单线程模型,数据顺序提交,redis支持主从模式,mencache只支持一致性hash做分布式;redis支持数据落地,rdb定时快照和aof实时记录操作命令的日志备份,memcache不支持;redis数据类型丰富,有string,hash,set,list, sort set,而memcache只支持简单数据类型;memcache使用cas乐观锁做一致性。
jedis操作Hash:hmset, hmget, hdel, hkeys
jedis操作List: lpush,lrange按照范围取出,rpush, del, sort等keyjedis操作Set:sadd,srem移除noname,smembers, sismember, scard等。summary.note
使用场景例如
Hash:存储读取更新用户多个属性
List:微博TimeLine,消息列表
Set:共同好友,二度好友,用唯一性可以统计网站所有独立IP,好友推荐根据tag求交集,大于threshold就可以推荐。
sortset:set增加1个权重score参数
其他场景:A订阅发布系统,redis对某个key消息发布及订阅,当1个key消息发布后,所有订阅它的客户端都会收到相应消息,例如实时消息系统,即时聊天,群聊等。
事务-常用EX,EC提交执行的命令,在server不出问题,可以保证一连串的命令是顺序执行额;提供1个watch功能,对1个key作watch,然后再执行transation。
redis内存数据上升到一定大小会执行数据淘汰策略,redis提供了6种数据淘汰策略。
LRU:从已设置过期时间的数据集合中挑选最近最少使用的数据淘汰
random:从已设置过期时间的数据中挑选任意数据淘汰
ttl:从已设置过期时间的数据集合中挑选将要过期的数据淘汰。
notenvision:禁止驱逐数据
如mysql中有2千万数据,redis只存储20万的热门数据。LRU或者TTL都满足热点数据读取较多,不太可能超时特点。
redis特点:速度块,O(1),丰富的数据类型,支持事物原子性,可用于缓存,比memecache速度块,可以持久化数据。
常见问题和解决:Master最好不做持久化如RDB快照和AOF日志文件;如果数据比较重要,某分slave开启AOF备份数据,策略为每秒1次,为了主从复制速度及稳定,MS主从在同一局域网内;主从复制不要用图状结构,用单向链表更为稳定 M-S-S-S-S。。。。;redis过期采用懒汉+定期,懒汉即get/set时候检查key是否过期,过期则删除key,定期遍历每个DB,检查制定个数个key;结合服务器性能调节并发情况。
过期淘汰,数据写入redis会附带1个有效时间,这个有效时间内该数据被认为是正确的并不关心真实情况,例如对支付等业务采用版本号实现,redis中每一份数据都维持1个版本号,DB中也维持1份,只有当redis的与DB中的版本一致时,才会认为redis为有效的,不过仍然每次都要访问DB,只需要查询version版本字段即可。
答:redis 本身支持16个数据库,通过 数据库id 设置,默认为0。
例如jedis客户端设置。一:JedisPool(org.apache.commons.pool.impl.GenericObjectPool.Config poolConfig, String host, int port, int timeout, String password, int database);
第一种通过指定构造函数database字段选择库,不设置则默认0库。二:jedis.select(index);调用jedis的select方法指定。
(1)拆分集群
对于存在明显分界线的业务,可以按照业务、地域使用不同集群,这种拆分集群的思路是非常靠谱的。对于我们的场景,已经按照地域拆分了集群,且同一地域的子业务间分界线不明显,拆分过多的集群维护成本较高。
(2)调整滚动周期
根据保留时长调整index滚动周期是最简单有效的思路。例如保留3天的数据按天滚动,保留31天的数据按周滚动,保留一年的数据按月滚动。合理的滚动周期,可以在存储成本增加不大的情况下,大幅降低分片数量。
对于我们的场景,大部分数据保留31天,在按周滚动的情况下,集群的总分片数可以下降到6.5w~个。
(3)合理设置分片数和副本数
除个别子业务压力较高外,大部分业务压力较小,合理设置单Index的分片数效果也不错。我们的经验是单个分片的大小在10GB~30GB之间比较合适,对于压力非常小的业务可以直接分配1个分片。其他用户可结合具体场景考虑,同时注意单分片的记录条数不要超过上限2,147,483,519。
在平衡我们的业务场景对数据可靠性的要求 及 不同副本数对存储成本的开销 两个因素之后,我们选择使用一主一从的副本策略。
目前我们集群单Index的平均分配数为3,集群的总分片数下降到3w~个。
(4)分片分配流程优化
默认情况下,ES在分配分片时会考虑分片relocation对磁盘空间的影响。在分片数较少时,这个优化处理的副作用不明显。但随着单机分片数量的上升,这个优化处理涉及的多层循环嵌套过程耗时愈发明显。可通过cluster.routing.allocation.disk.include_relocations: false关闭此功能,这对磁盘均衡程度影响不明显。
(5)预创建Index
对于单集群3w分片的场景,集中在每周某天0点创建Index,对集群的压力还是较大,且存储空间存在波动。考虑到集群的持续扩展能力和可靠性,我们采用预创建方式提前创建分片,并把按Index的创建时间均匀打散到每周的每一天。
(6)持续调整分片数
对于集群分片的调整,通常不是一蹴而就的。随着业务的发展,不断新增的子业务 或 原有子业务规模发生突变,都需要持续调整分片数量。
默认情况下,新增的子业务会有默认的分片数量,如果不足,会在测试阶段及上线初期及时发现。随着业务发展,系统会考虑Index近期的数据量、写入速度、集群规模等因素,动态调整分片数量。
使用scroll(有状态)和search after(无状态)的游标方式。
三个文件:字典文件,频率文件,位置文件。词典文件不仅保存有每个关键词,还保留了指向频率文件和位置文件的指针,通过指针可以找到该关键字的频率信息和位置信息。
field的概念,用于表达信息所在位置(如标题中,文章中,url中),在建索引中,该field信息也记录在词典文件中,每个关键词都有一个field信息(因为每个关键字一定属于一个或多个field)。
关键字是按字符顺序排列的(lucene没有使用B树结构),因此lucene可以用二元搜索算法快速定位关键词。
假设要查询单词 “live”,lucene先对词典二元查找、找到该词,通过指向频率文件的指针读出所有文章号,然后返回结果。词典通常非常小,因而,整个过程的时间是毫秒级的。
对词典文件中的关键词进行了压缩,关键词压缩为<前缀长度,后缀>,例如:当前词为“阿拉伯语”,上一个词为“阿拉伯”,那么“阿拉伯语”压缩为<3,语>。对数字的压缩,数字只保存与上一个值的差值。