范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

面试题之java缓存总结,从单机缓存到分布式缓存架构

  1、缓存定义
  高速数据存储层,提高程序性能  2、为什么要用缓存(读多写少,高并发)1、提高读取吞吐量 2、提升应用程序性能 3、降低数据库成本 4、减少后端负载 5、消除数据库热点 6、可预测的性能 3、缓存分类3.1、单机缓存(localCache)实现方案1、基于JSR107规范自研(了解即可):
  1、Java Caching定义了5个核心接口,分别是CachingProvider, CacheManager, Cache, Entry 和 Expiry。
  2、CachingProvider定义了创建、配置、获取、管理和控制多个CacheManager。一个应用可以在运行期访问多个CachingProvider。
  3、CacheManager定义了创建、配置、获取、管理和控制多个唯一命名的Cache,这些Cache存在于CacheManager的上下文中。一个CacheManager仅被一个CachingProvider所拥有。
  4、Cache是一个类似Map的数据结构并临时存储以Key为索引的值。一个Cache仅被一个CacheManager所拥有。
  5、Entry是一个存储在Cache中的key-value对。
  每一个存储在Cache中的条目有一个定义的有效期,即Expiry Duration。
  一旦超过这个时间,条目为过期的状态。一旦过期,条目将不可访问、更新和删除。缓存有效期可以通过ExpiryPolicy设置。  2、基于ConcurrentHashMap实现数据缓存3.2、分布式缓存(redis、Memcached)4、单机缓存1、自己实现一个单机缓存创建缓存类/**  * @author yinfeng  * @description 本地缓存实现:用map实现一个简单的缓存功能  * @since 2022/2/8 13:54  */ public class MapCacheDemo {      /**      * 在构造函数中,创建了一个守护程序线程,每5秒扫描一次并清理过期的对象      */     private static final int CLEAN_UP_PERIOD_IN_SEC = 5;      /**      * ConcurrentHashMap保证线程安全的要求      * SoftReference   作为映射值,因为软引用可以保证在抛出OutOfMemory之前,如果缺少内存,将删除引用的对象。      */     private final ConcurrentHashMap> cache = new ConcurrentHashMap<>();      public MapCacheDemo() {         //创建了一个守护程序线程,每5秒扫描一次并清理过期的对象         Thread cleanerThread = new Thread(() -> {             while (!Thread.currentThread().isInterrupted()) {                 try {                     Thread.sleep(CLEAN_UP_PERIOD_IN_SEC * 1000);                     cache.entrySet().removeIf(entry -> Optional.ofNullable(entry.getValue()).map(SoftReference::get).map(CacheObject::isExpired).orElse(false));                 } catch (InterruptedException e) {                     Thread.currentThread().interrupt();                 }             }         });         cleanerThread.setDaemon(true);         cleanerThread.start();     }      public void add(String key, Object value, long periodInMillis) {         if (key == null) {             return;         }         if (value == null) {             cache.remove(key);         } else {             long expiryTime = System.currentTimeMillis() + periodInMillis;             cache.put(key, new SoftReference<>(new CacheObject(value, expiryTime)));         }     }      public void remove(String key) {         cache.remove(key);     }      public Object get(String key) {         return Optional.ofNullable(cache.get(key)).map(SoftReference::get).filter(cacheObject -> !cacheObject.isExpired()).map(CacheObject::getValue).orElse(null);     }      public void clear() {         cache.clear();     }      public long size() {         return cache.entrySet().stream().filter(entry -> Optional.ofNullable(entry.getValue()).map(SoftReference::get).map(cacheObject -> !cacheObject.isExpired()).orElse(false)).count();     }      /**      * 缓存对象value      */     private static class CacheObject {         private Object value;         private final long expiryTime;          private CacheObject(Object value, long expiryTime) {             this.value = value;             this.expiryTime = expiryTime;         }          boolean isExpired() {             return System.currentTimeMillis() > expiryTime;         }          public Object getValue() {             return value;         }          public void setValue(Object value) {             this.value = value;         }     }     }写个main方法测试一下public static void main(String[] args) throws InterruptedException {         MapCacheDemo mapCacheDemo = new MapCacheDemo();         mapCacheDemo.add("uid_10001", "{1}", 5 * 1000);         mapCacheDemo.add("uid_10002", "{2}", 5 * 1000);         System.out.println("从缓存中取出值:" + mapCacheDemo.get("uid_10001"));         Thread.sleep(5000L);         System.out.println("5秒钟过后");         // 5秒后数据自动清除了         System.out.println("从缓存中取出值:" + mapCacheDemo.get("uid_10001"));     }2、谷歌guava cache缓存框架2.1、简介
  Guava Cache是一个内存缓存模块,用于将数据缓存到jvm内存中,是单个应用运行时的本地缓存,他不将数据放到文件或外部服务器。  2.2简单使用/**  * @author yinfeng  * @description guava测试,https://github.com/google/guava  * @since 2022/2/8 14:13  */ public class GuavaCacheDemo {     public static void main(String[] args) throws ExecutionException {         //缓存接口这里是LoadingCache,LoadingCache在缓存项不存在时可以自动加载缓存         LoadingCache userCache                 //CacheBuilder的构造函数是私有的,只能通过其静态方法newBuilder()来获得CacheBuilder的实例                 = CacheBuilder.newBuilder()                 //设置并发级别为8,并发级别是指可以同时写缓存的线程数                 .concurrencyLevel(8)                 //设置写缓存后8秒钟过期                 .expireAfterWrite(8, TimeUnit.SECONDS)                 //设置写缓存后1秒钟刷新                 .refreshAfterWrite(1, TimeUnit.SECONDS)                 //设置缓存容器的初始容量为10                 .initialCapacity(10)                 //设置缓存最大容量为100,超过100之后就会按照LRU最近虽少使用算法来移除缓存项                 .maximumSize(100)                 //设置要统计缓存的命中率                 .recordStats()                 //设置缓存的移除通知                 .removalListener(notification -> System.out.println(notification.getKey() + " 被移除了,原因: " + notification.getCause()))                 //build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存                 .build(                         new CacheLoader() {                             @Override                             public User load(String key) {                                 System.out.println("缓存没有时,从数据库加载" + key);                                 // TODO jdbc的代码~~忽略掉                                 return new User("yinfeng" + key, key);                             }                         }                 );         // 第一次读取         for (int i = 0; i < 20; i++) {             User user = userCache.get("uid" + i);             System.out.println(user);         }         // 第二次读取         for (int i = 0; i < 20; i++) {             User user = userCache.get("uid" + i);             System.out.println(user);         }         System.out.println("cache stats:");         //最后打印缓存的命中率等 情况         System.out.println(userCache.stats().toString());     }      @Data     @AllArgsConstructor     public static class User implements Serializable {         private String userName;         private String userId;         @Override         public String toString() {             return userId + " --- " + userName;         }     } }5、分布式缓存5.1redis5.1.1介绍
  Redis是一个开源的使用C语言缩写、支持网络、可基于内存亦可持久化的日志型,Key-Value数据库,并提供多种语言的API。
  本质是客户端-服务端应用软件程序。
  特点是使用简单,性能强悍,功能应用场景丰富。  5.1.2通用命令
  命令
  作用
  DEL key
  用于在key存在是删除key
  DUMP key
  序列化给定的key,并返回给定的值
  EXISTS key
  检查给定key是否存在
  EXPIRE key seconds
  为给定key设置过期时间,单位秒
  TTL key
  以秒为单位,返回给定key的剩余生存时间
  TYPE key
  返回key所存储的值的类型  5.1.3数据结构1.String定义
  String数据结构是简单的key-value类型,value其实不仅是String,也可以是数字。
  使用场景:微博数,粉丝数(常规计数)  常用命令
  命令
  作用
  Get
  获取指定key的值
  Set
  设置指定key的值
  Incr
  将key中储存的数字值增一
  Decr
  将key中储存的数字值减一
  Mget
  获取所有(一个或多个)给定key的值  2. List定义
  List就是链表,依赖于链表结构
  使用场景:微博的关注列表,粉丝列表  常用命令
  命令
  作用
  Lpush
  将一个或多个值插入到列表头部
  Rpush
  在列表中添加一个或多个值
  Lpop
  移出并获取列表的第一个元素
  Rpop
  移除列表的最后一个元素,返回值为移除的元素
  Lrange
  获取所有(一个或多个)给定key的值  3. Set定义
  Set就是一个集合,集合的概念就是一堆不重复值的组合。利用Reds提供的Set数据结构,可以存储一些集合性的数据。
  使用场景:实现如共同关注,共同喜好,二度好友  常用命令
  命令
  作用
  Lpush
  向集合中添加一个或多个成员
  Rpush
  移除并返回集合中的一个随机元素
  Lpop
  返回集合中的所有成员
  Rpop
  返回所有给定集合的并集  4. Sorted set定义
  Sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。
  使用场景:排行榜、按照用户投票和时间排序  常用命令
  命令
  作用
  Zadd
  向有序集合添加一个或多个成员,或者更新已存在成员的分数
  Zrange
  通过索引区间返回有序集合中指定区间内的成员
  Zrem
  移除有序集合中的一个或多个成员
  Zcard
  获取有序集合的成员数  5. Hash定义
  Hash是一个sting类型的field和value的映射表
  使用场景:存储部分变更数据,如用户信息  常用命令
  命令
  作用
  Zadd
  获取存储在哈希表中指定字段的值
  Zrange
  将哈希表key中的字段field的值设为value
  Hgetall
  获取在哈希表中指定key的所有字段和值  6. GEO定义
  GEO3.2版本开始对GEO(地理位置)的支持
  使用场景:LBS应用开发  常用命令
  命令
  作用
  GEOADD
  增加地理位置的坐标,可以批量添加地理位置
  GEODIST
  获取两个地理位置的距离
  GEOHASH
  获取某个地理位置的geohash值
  GEOPOS
  获取指定位置的坐标,可以批量获取多个地理位置的坐标
  GEORADIUS
  根据给定地理位置坐标获取指定范围内的地理位置集合(注意:该命令的中心点由输入的经度和结度决定)
  GEORADIUSBYMEMBER
  根据给定成员的位置获取指定范围内的位置信息集合(注意:该命令的中心点足由给定的位置元素决定)  7. Stream定义
  Stream5.0版本开始的新结构"流"
  使用场景:消费者生产者场景(类似MO)  常用命令
  命令
  作用
  XADD
  增加地理位置的坐标,可以批量添加地理位置
  XLEN
  stream流中的消息数量
  XDEL
  删除流中的消息
  XRANGE
  返回流中满足给定ID范围的消息
  XREAD
  从一个或者多个流中读取消息
  XINFO
  检索关于流和关联的消费者组的不同的信息  5.1.4持久化机制1. 介绍
  redis的数据都存放在内存中,如果没有配置持久化,重启后数据就全丢失,于是需要开启redis的持久化功能,将数据保存到磁盘上,当redis重启后,可以从磁盘中恢复数据  2. 持久化方式RDB持久化:RDB持久化方式能够在指定的时间间隔对你的数据进行快照存储  AOF持久化: AOF持久化方式记录每次对服务器写的操作,当服务器重后的时候会重新执行这些命令来恢复原始的数据  3.RDB方式
  客户端直接通过命令BGSAVE或者SAVE来创建一个内存快照:  BGSAVE调用fork来创建一个子进程,子进程负责将快照写入磁盘,而父进程仍然继续处理命令。  SAVE执行SAVE命令过程中,不再响应其他命令。  在redis.conf中调整save配置选项,当在规定的时间内,redis发生了写操作的个数满足条件会触发BGSAVE命令#900秒之内至少一次写操作 save 900 1 #300秒之内至少发生10次写操作 save 300 10优缺点
  优点
  缺点
  对性能影响最小
  同步时丢失数据
  RDB文件进行数据恢复比使用AOF要快很多
  如果数据集非常大且CPU不够强(比如单核CPU),Redis在fork子进程时可能会消耗相对较长的时间,影响RediS对外提供服务的能力  4. AOF持久化方式
  **开启AOF持久化 **  appendonty yesAOF策略调整#每次有数据修改发生时都会写入AOF文件 appendfsync always #每秒钟同步一次,该策略为AOF的默认策略 appendfsync everysec #从不同步。高效但是数据不会被持久化 appendfsync no优点
  优点
  缺点
  最安全
  文件体积大
  容灾
  性能消耗比RDB高
  易读,可修改
  数据恢复速度比RDB慢  5.1.5 内存管理1、内存分配不同数据类型的大小限制:Strings类型:一个Strings类型的Value最大可以存储512M。 Lists类型:list的元素个数最多为2^32-1个 Sets类型:元素个数最多为2^32-1个 Hashes类型:键值对个数最多为2^32-1个 最大内存控制:maxmemory 最大内存阈值 maxmemory-policy 到达阈值的执行策略 2、内存压缩#配置字段最多512个 hash-max-zipmap-entries 512 #配置value最大为64字节 hash-max-zipmap-value 64 #配置元素个数最多512个 lst-max-zipmap-entries 512 #配置value最大为64字节 list-max-zipmap-value 64 #配置元素个数最多512个 set-max-zipmap-entries 512
  大小超出压缩范围,溢出后redis将自动将其转换为正常大小  3、过期数据的处理策略主动处理(redis主动触发检测key足否过期)每秒抗行10次。过程如下:从具有相关过期的key集合中测试20个随机key  删除找到的所有已过期key  如果超过25%的key已过期,请从步骤1重新开始  被动处理:每次访问key的时候,发现超时后被动过期,清理掉  数据恢复阶段过期数据的处理策略:
  RDB方式:过期的Key不会被持久化到文件中。载入时过期的key,会通过redis的主动和被动方式清理掉。
  AOF方式:每次遇到过期的key,redis会追加一条DEL命令到AOF文件,也就是说只要我们顺序载入执行AOF命令文件就会删除过期的key
  注意:过期数据的计算和计算机本身的时间是有直接联系的!  Redis内存回收策略:
  配置文件中设置:maxmemory-poIicy noeviction
  命令动态调整:config set maxmemory-policy noeviction
  回收策略
  说明
  noeviction
  客户端尝试执行会让更多内存被使用的命令直接报错
  allkeys-lru
  在所有key里执行LRU算法清除
  volatile-lru
  在所有已经过期的key里执行LRU算法清除
  allkeys-lfu
  在所有key里执行LFU算法清除
  volatile-lfu
  在所有已经过期的key里执行LFU算法清除
  allkeys-random
  在所有key里随机回收
  volatile-random
  在已经过期的key里随机回收
  volatile-ttl
  回收已经过期的key,并且优先回收存活时间(TTL)较短的key  4、LRU算法LRU(最近最少使用):根据数据的历史访问记录来进行沟汰数据
  核心思想:如果数据最近被访问过,那么将来被访问的几率也更高。
  注意:Redis的LRU算法并非完整的实现,完整的LRU实现需要太多的内存。
  方法:通过对少量keys进行取样(50%),然后回收其中一个最好的key。
  配置方式:maxmemory-samples 5  5、LFU算法LFU:根据数据的历史访问频率来沟汰数据
  核心思想:如果数据过去被访问多次,那么将来被访问的频率也更高。
  启用LFU算法后,可以使用热点数据分析功能。  5.1.6 主从复制1、介绍为什么要主从复制
  redis-server单点故障
  单节点QPS有限  应用场景分析
  读写分离场景,规避redis单机瓶颈
  故障切换,master出问题后还有slave节点可以使用  2、搭建主从复制主Redis Server以普通模式启动,主要是启动从服务器的方式命令行  #连接需要实现从节点的rediS,执行下面的命令    slaveof   [ip] [port] redis.conf配置文件  #配置文件中增加    slaveof   [ip] [port]  #从服务器是否只读(默认yes)   slave-read-only  yes  退出主从集群的方式  slaveof     no   one 3、检查主从复制#redis客户端执行 info replication4、主从复制流程从服务器通过psync命令发送服务器已有的同步进度(同步源ID,同步进度offset)  master收到请求,同步源为当前master,则根据偏移量增量同步  同步源非当前master,则进入全量同步:maser生成rdb,传输到slave,加载到slave内存  5、主从复制核心知识Redis默认使用异步复制,slave和master之间异步地确认处理的数据量  一个master可以拥有多个slave  Slave可以接受其他slave的连接。slave可以有下级sub slave  主从同步过程在master侧是非阻塞的  slave初次同步需要删除旧数据,加载新数据,会阻塞到来的连接请求  6、应用场景主从复制可以用来支持读写分离  slave服务器设定为只读,可以用在数据安全的场景下。  可以使用主从复制来避免master持久化造成的开销。master关闭持久化,slave设置为不定期保存或开启AOF  注意   :重新启动的master程序将从一个空数据集开始,如果一个slave试图与它同步,那么这个slave也会被清空。  7、注意事项读写分离场景:数据复制延时导致读到过期数据或者读不到数据(网络原因,slave阻塞)从节点故障(多个client如何迁移)  全量复制情况下:第一次建立主从关系或者runid不匹配会导致全量复制故障转移的时候也会出现全量复制  复制风暴:master故障重启,如果slave节点过多,所有slave都要复制,对服务器的性能,网络的压力都有很大影响。如果一个机器部署了多个master  写能力有限主从复制还是只有一台master,提供的写服务能力有限  master故障情况下:如果是mater无持久化,Slave开启持久化来保留数据的场展,建议不要配置redis自动重启。启动redis自动重启,master启动后,无备份数据,可能导致集群数据丢失的情况  带有效期的key:Slave不会让key过期,而是等待master让key过期在Lua脚本执行期间,不执行任何key过期操作  5.1.7 哨兵模式1、哨兵(Sentinel)机制核心作用
  客户端询问主redis地址> redis哨兵监控、提醒、故障转移(主从切换)> 主redis(master)主从复制关系> 从redis(slave)  2、核心运作流程服务发现和健康检查流程
  搭建redis主从集群 ==> 启动哨兵(客户端通过哨兵发现Redis实例信息) ==> 哨兵通过连接master发现主从集群内的所有实例信息 ==> 哨兵监控redis实例的健康状况  故障切换流程
  哨兵一旦发现master不能正常提供服务,则通知给其他哨兵 ==> 当一定数量的哨兵都认为master挂了 ==> 选举一个哨兵作为故障转移的执行者 ==> 执行者在slave中选取一个作为新的master ==> 将其他slave重新设定为新master的从属  3、哨兵如何知道Redis主从信息
  哨兵配置文件中,保存着主从集群中master的信息,可以通过info replication命令,进行主从信息自动发现。  4、什么是主观下线(sdown)
  主观下线:单个哨兵自身认为redis实例已经不能提供服务
  检测机制:哨兵向redis发送ping请求,+PONG,-LOADING,-MASTERDOWN三种情况视为正常,其他回复均视为无效
  对应配置文件的配置项:sentinel down-after-milliseconds mymaster 1000  5、什么是客观下线(odown)
  客观下线:一定数量值的哨兵认为master已经下线。
  检测机制:当哨兵主观认为maser下线后,则会通过SENTINEL is-master-down-by-addr命令询问其他哨兵是否认为master已经下线,如果达成共识(达到quorum个数),就会认为master节点客观下线,开始故障转移流程
  对应配置文件的配置项:sentinel monitor mymaster 1.0.0.1 6380 2  6、哨兵之间如何通信哨兵之间的自动发现:发布自己的信息,订阅其他哨兵消息(pub/sub)  哨兵之间通过命令进行通信:直连发送命令  哨兵之间通过订阅发布进行通信:相互订阅指定主题(pub/sub)  7、哨兵领导选举机制基于Raft算法实现的选举机制,流程简述如下:拉票阶段:每个哨兵节点希望自己成为领导者;  Sentinel节点收到拉票命令后,如果没有收到或同意过其他sentinel节点的请求,就同意该sentinel节点的请求(每个sentinel只持有一个同意票数)  如果sentinel节点发现自己的票数已经超过一半的数值,那么它将成为领导者,去执行故障转移  投票结束后,如果超过failover-timeout的时间内,没进行实际的故障转移操作,则重新拉票选举。  8、slave选举方案
  slave节点状态 > 优先级 > 数据同步情况 > 最小的run id  9、最终主从切换的过程
  针对即将成为master的slave节点,将其撒出主从集群,自动执行:slaveof NO ONE
  针对其他slave节点,使它们成为新master的从属,自动执行:slaveof new_master_host new_master_port  10、哨兵服务部署方案
  不推荐:一主一从,两个哨兵
  推荐:一主两从,三个哨兵
  redis集群非强一致:一主两从,网络分区下可能出现数据不一致或丢失。  5.1.8 redis集群分片存储1、为什么要分片存储
  redis的内存需求可能超过机器的最大内存。(一台机器不够用)  2、官方集群方案
  redis cluster是redis的分布式集科解决方案,在3.0版本推出后有效地解决了redis分布式分面的需求,实现了数据在多个Redis节点之间自动分片,故障自动转移,扩容机制等功能。
  主要基于CRC16(key) % 16384 计算出每个key对应的slot,然后根据redis集群中实例的预设槽slot(16384个)进行对应的操作,slot不存储数据,仅仅用来做片区划分。  3、搭建集群准备6个独立的redis服务  通过redis-cli工具创建集群  检验集群  故障转移测试  集群扩容  集群节点删除  4、集群关心的问题增加了slot槽的计算,是不是比单机性能差?不是的,为了避免每次都需要服务器计算重定向,优秀的Java客户端都实现了本地计算,并且缓存服务器slots分配,有变动时再更新本地内容,从而避免了多次重定向带来的性能损耗。  redis集群大小,到底可以装多少数据?理论是可以做到16384个槽,每个槽对应一个实例,但是redis宫方建议是最大1000个实例,因为存储已经足够大了。  集群节点间是怎么通信的?每个Redis群集节点都有一个额外的TCP端口,每个节点使用TCP连接与每个其他节点连接。检测和故障转移这些步骤基本和哨兵模式类似。  ask和moved重定向的区别  重定向包括两种情况  若确定slot不属于当前节点,redis会返回moved。若当前redis节点正在处理slot迁移,则代表此处请求对应的key暂时不在此节点,返回ask,告诉客户端本次请求重定向。  数据倾斜和访问倾斜的问题  倾斜导致集群中部分节点数据多,压力大。解决方案分为前期和后期:  前期是业务层面提前预测,哪些key是热点,在设计的过程中规避。后期是slot迁移,尽量将压力分摊(slot调整有自动rebalance、reshard和手动)。  slot手动迁移怎么做?在迁移目的节点执行cluster setslot IMPORTING 命令,指明需要迁移的slot和迁移源节点。在迁移源节点执行cluster setslot MIGRATING 命令,指明需要迁移的slot和迁移目的节点。在迁移源节点执行cluster getkeysinslot获取该slot的key列表在迁移源节点执行对每个key执行migrate命令,该命令会同步把该key迁移到目的节点。在迁移源节点反复执行cluster getkeysinslo命令,直到该slot的列表为空。在迁移源节点和目的节点执行cluster setslot NODE ,完成迁移操作。  节点之间会交换信息,传递的消息包括槽的信息,带来带宽消耗。   注意   :避免使用大的一个集群,可以分多个集群。  Pub/Sub发布订阅机制:对集群内任意的一个节点执行pubish发布消息,这个消息会在集群中进行传播,其他节点都接收到发布的消息。  读写分离:redis-cluster默认所有   从节点上的读写   ,都会重定向到key对应槽的主节点上。可以通过readonly设置当前连接可读,通过readwrite取消当前连接的可读状态。注意:主从节点依然存在数据不一致的问题  5.1.9 redis监控1、monitor命令
  monitor是一个调试命令,返回服务器处理的每个命令。对于发现程序的错误非常有用。出于安全考虑,某些特殊管理命令CONFIG不会记录到MONITOR输出。
  注意:运行一个MONITOR命令能够降低50%的吞吐量,运行多个MONITOR命令降低的吞吐量更多。  2、info命令
  INFO命令以一种易于理解和阅读的格式,返回关于Redis服务器的各种信息和统计数值。
  info命令
  返回信息
  server
  Redis服务器的一般信息
  clients
  客户端的连接部分
  memory
  内存消耗相关信息
  persistence
  持久化相关信息
  stats
  一般统计
  replication
  主/从复制信息
  cpu
  统计CPU的消耗
  commandstats
  Redis命令统计
  cluster
  Redis集群信息
  keyspace
  数据库的相关统计
  可以通过section返回部分信息,如果没有使用任何参数时,默认为detault。  3、图形化监控工具: Redis-Live5.2 memcached入门由于memcached慢慢淡出了人们的视野,使用的公司越来越少,所以这里只是做个入门介绍。1、简介是一个免费开源的、高性能的、具有分布式内存对象的缓存系统,它通过减轻数据库负载加速动态web应用。
  本质上就是一个内存key-Value缓存
  协议简单,使用的是基于文本行的协议
  不支持数据的持久化,服务器关闭之后数据全部丢失
  Memcached简洁而强大,便于快速开发,上手较为容易
  没有安全机制  2、设计理念简单的键/值存储:服务器不关心你的数据是什么样的,只管数据存储  服务端功能简单,很多逻辑依赖客户端实现客户端专注如何选择读取或写入的服务器,以及无法联系服务器时要执行的操作。服务器专注如何存储和管理何时清除或重用内存  Memcached实例之间没有通信机制  每个命令的复杂度为0(1):慢速机器上的查询应该在1ms以下运行。高端服务器的吞吐量可以达到每秒数百万  缓存自动清除机制  缓存失效机制  3、常用命令
  分组
  命令
  描述
  存储命令
  set
  用于将value存储在指定的key中。key已经存在,更新该key所对应的原来的数据。
  add
  用于将value存储在指定的key中,存在则不更新。
  replace
  替换已存在的key的Value,不存在,则替换失败。
  append
  用于向已存在key的value后面追加数据
  prepend
  向已存在key的value前面追加数据
  cas
  比较和替换,比对后,没有被其他客户端修改的情况下才能写入。
  检索命令
  get
  获取存储在key中的value,不存在,则返回空。
  gets
  获取带有CAS令牌存的value,若key不存在,则返回为空
  删除
  delete
  删除已存在的key
  计算
  incr/decr
  对已存在的key的数字值进行自增或自减操作
  统计
  stats
  返回统计信息如PID(进程号)、版本号、连接数等
  stats items
  显示各个slab中item的数目和存储时长(最后一次访问距离现在的秒数)
  stats slabs
  显示各个slab的信息,包括chunk的大小、数目、使用情况等。
  stats sizes
  显示所有item的大小和个数
  清除
  flush_all
  清除所有内容  4、客户端使用
  客户端支持的特性:集群下多服务器选择,节点权重配置,失败/故障转移,数据压缩,连接管理  5、服务端配置命令行参数查看memcached-h或man memcached获取最新文档  init脚本如果通过yum应用商店安装,可以使用/etc/sysconfig/memcached文件进行参数配置  检查运行配置stats settings查看运行中的memcached的配置  6、memcached性能
  Memcached性能的关键是硬件,内部实现是hash表,读写操作都是0(1)。硬件好,几百万的OPS都是没问题的。
  最大连接数限制:内部基于事件机制(类似JAVA NIO)所以这个限制和nio类似,只要内存,操作系统参数进行调整,轻松几十万。
  集群节点数量限制:理论是没限制的,但是节点越多,客户端需要建立的连接就会越多。
  注意:memcached服务端没有分布式的功能,所以不论是集群还是主从备份,都需要第三方产品支持。  7、服务器硬件需要
  CPU要求:CPU占用率低,默认为4个工作线程  内存要求:
  memcached内容存在内存里面,所有内存使用率高。
  建议memcached实例独占服务器,而不是混用。
  建议每个memcached实例内存大小都足一致的,如果不一致则需要进行权重调整  网络要求:
  根据项目传输的内容来定,网络越大越好,虽然通常10M就够用了
  建议:项目往memcached传输的内容保持尽可能的小  8、Memcached应用场景数据查询缓存   :将数据库中的数据加载到memcached,提供程序的访问速度  计数器的场景   :通过incr/decr命令实现评论数量、点击数统计,操作次数等等场景。  乐观锁实现   :例如计划任务多实例部暑的场景下,通过CAS实现不重复执行  防止重复处理   :CAS命令  5.3 互联网高并发缓存架构5.3.1 缓存架构分析图
  5.3.2 缓存雪崩
  定义:因为缓存服务挂掉或者热点缓存失效,从而导致所有请求都去查数据库,导致数据库连接不够用或者数据库处理不过来,从而导致整个系统不可用。  常用解决方案:缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。  缓存降级,直接返回错误码;  加锁实现防止大量请求堆到数据库。  设置热点数据永远不过期,防止了自动失效的情况,通过其他后台检查程序,防止缓存数据和数据库长期不同步  5.3.2 缓存击穿
  定义:查询必然不存在的数据,请求透过Redis,直击数据库。  常用解决方案:用户内容预生成。  访问频率限制。  缓存中无数据,也不查询数据库,直接返回错误码。  布隆过滤器
  原文链接:https://www.cnblogs.com/yin-feng/p/15894104.html?utm_source=tuicool&utm_medium=referral
来杨家坪感受好物市集边吃边逛边买真的太有趣按照发展蓝图,抓好十项行动。伴随着消费市场的快速复苏,商圈人气爆棚景区人流如织。杨家坪商圈作为重庆老牌商圈和九龙坡区的城市中心,不仅拥有时髦高档的万象城烟火十足的特色街区和书香味浓全媒文旅宁德市举行游轮试航仪式为响应福建省文旅经济发展大会主题,加快我市山水海岛礁滩湾一体化开发,构建以滨海休闲度假为核心的旅游产品体系,4月16日,市旅发集团在宁德港务集团7号趸船码头举办游轮试航仪式。据悉,白银马拉松牧羊人大叔和被救者在郑州跑半马,朱可铭有很多厉害的选手,我是中下游4月16日,甘肃白银马拉松中救人的牧羊人朱可铭与被救者张小涛在郑州参加马拉松比赛,引发关注。当天,朱可铭告诉九派新闻,自己没有拿到名次,现场有很多厉害的选手,我只能算是中下游。朱可2023年世界泳联跳水世界杯西安站陈芋汐力压全红婵摘金图为陈芋汐。张远摄图为全红婵。张远摄图为陈芋汐。张远摄图为陈芋汐。张远摄图为全红婵。张远摄图为全红婵。张远摄图为全红婵。张远摄4月16日,2023年世界泳联跳水世界杯西安站进入收官续约!恭喜皇马!2核心留队,完成协议,无视2000万诱惑,不理C罗确定了,两位中场核心老将再和皇马续约一年。在西甲积分榜被巴萨甩开10分后,皇马正式宣告与争冠无缘,俱乐部上下将全部精力投入到欧冠和国王杯赛场上。管理层对这种情况早有预估,皇家马德里CBA季后赛,媒体人透露打假球处罚准则禁赛25年,罚500万最近CBA季后赛继继续火热进行中,在周一即将迎来八强的比赛。值得一提的是在这一次比赛即将到来,很多球迷依旧关注着江苏男篮以及上海男篮比赛结束之后传出的假球传闻。毕竟这件事情的影响非扫雷说让球说庆祝说抽签说只为陈梦定制,为何对他人无效?在奥运会女单决赛结束后,对陈梦的攻击谩骂就始终没有停止,包括扫雷说让球说激情庆祝说抽签作弊说等等,各种歪门邪说铺天盖地,压得陈梦缓不过气来。有人会说,这都猴年马月的事了,现在还讨论跳水世界杯西安站女子3米板陈艺文昌雅妮晋级决赛4月15日,陈艺文在比赛中。当日,在陕西省西安市奥体中心举行的2023年跳水世界杯西安站女子3米板预赛中,中国选手陈艺文昌雅妮分别以预赛第一二名的成绩晋级决赛。新华社记者张博文摄4让自己生活变富裕的30个小建议头条创作挑战赛1hr不要让自己闲着,想想自己能做什么,该做什么。一定要有工作,即使没有,也要通过务农,劳务,找到能得到收入的工作。没有就去找,做各种努力。先保证温饱,再求富裕。2h让自己越来越好的十个建议拥抱内心的正能量。像珍惜生命一样珍惜时间时间是一个人最宝贵的财富,如何利用时间,代表了我们对待人生的态度。有人把时间用来自我提升把时间用来与爱人分享,有人把时间消耗在平庸的享乐中。吃完烧烤,来聊城!四方食事,抵不过一串人间烟火。近段时间,全国各地的食客扎堆前往淄博,天还没黑,烧烤店门口的方桌前,已是满满当当,空气里全是烤肉的香味。殊不知,咱聊城也是美食的天堂。这个春天,总要来
90的人食用油脂超标!我们不被重视的隐形油藏在哪里?食用的油量严重超标是患有高血脂肥胖症的主要原因!究竟是哪些食物含有丰富的油脂呢?今天,我们一起来聊一聊我们身边的隐形油。食用油是我们生活中必不可少的部分,也是我们热量的重要来源,是白裤子搭什么都好看,一条裤子穿出25种搭配,优雅又大方自入冬以来,我购置了不少单品,基本把衣橱都更新了一波。要说我冬日利用率最高的一件单品,白裤子必须拥有姓名。清爽百搭时髦,堪称裤子届的气质担当。冬季不管是气候还是氛围都萧瑟凄凄,在穿中国女排涌现3位主攻新星!张常宁多一个对角,栗垚找到好帮手排超联赛即将进行决赛阶段的比拼,天津女排与江苏女排会师决赛。由于今年是赛事大年,奥运会和全运会同年举行,导致各支队伍的阵容发生巨大变化,许多年轻小将从青年队成功升入到成年队。通过决易建联被轮番羞辱,与其这样,不如早点退役易建联被轮番羞辱,与其这样,不如早点退役亲情提示亲爱的读者,如何能每天能读到这样的体育资讯呢?点击右上角的关注按钮即可,您的关注将是我创作的最大动力!CBA第二阶段已经4轮战罢,不大气层有多大?原来月球只在地球的大气层中穿过一些天文学家发现地球的大气层比人们之前想象的大得多,甚至一直延伸到月球之外的更远的地方。这一区域被称作地面。是地球大气散逸层的一部分,因为包含中性氢元素,而会在紫外线的照射下发光的科幻作家的星际战争假想依据之前有读者质疑我们在太空真空无重力的环境下,以亚光速度高速在太空中飞行的两方人马的太空战舰是怎么停下来的?太空之城里的片段其实这个问题太小儿科了,对与已经可以在太空发动战争的人类文三国志战略版地区服嵩阳学院开启,跟着你的老乡共创霸业哈喽大家好,我是你们的白给。12月25日,三国志战略版第一个地区服正式上线官方为什么要将第一个地区服设为河南?我想那是因为河南的历史底蕴摆在那里正所谓得中原者得天下,自古中原乃兵家邮储银行全国网点最多,为何营收和利润跟四大行差距那么大?目前我国有4000多家法人银行机构,这里面最为人知的就是国有6大行和12家股份制银行。国有6大行,就是工商银行,建设银行,农业银行,中国银行,交通银行和邮储银行,其中邮储银行是最近幻塔出现Bug,玩家能卡武器,SSR拿到手软?这就,让人怎么说,而且根据bug的情况来看,产生bug的原因应该是抽卡做的本地结算,然后再传给服务器,因为没传递过去才出现了无限刷的bug,并且服务器是不对客户端传递过来的数据进行一年四季都在用洗面奶是什么感受我之所以一年四季都用洗面奶,是因为脸上超级油。不用洗面奶,油到反光,稍微用卫生纸一擦,就很多油的那种,用香皂洗脸会好点,但是不半个小时还是会很油,不是正常人油腻的那种。我太难了,冬被罚1000万美金,西蒙斯不为所动,与欧洲杨幂已订婚近几个月,关于76人队本西蒙斯的交易消息可谓遍布全网,自从上赛季休赛期西蒙斯与球队的关系出现隔阂后,他就不愿意再为76人队打球,一心只想着球队交易自己。但是,76人队的管理层也不是