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

Plumecache一个常见分布式缓存封装工具类库

  为什么有plumecache?
  日常项目开发中使用缓存的时候,无论选择redis、memcached,或是其它类型缓存,我们总要在做一些封装,才能很好的使用。plumecache是我个人缓存使用经验的一些总结,旨在于解决日常使用缓存时的一些问题和痛点,写出来和大家分享,也欢迎大家的star和issue Gitee地址简介
  Plumecache 是一个常见分布式缓存封装工具类库,降低相关client api学习成本,提高工作效率,当前支持reids(standalone,sentinel,cluster)、memcached
  Plumecache解决什么问题?1.用于替换项目中CacheService、CacheHelper、CacheHandler、CacheUtils等缓存工具类或胶水代码2.支持多缓存实例管理,解决既要还要的问题3.支持缓存key前缀、缓存版本的配置4.支持缓存序列化统一处理,不需要在每个调用的地方写序列化,支持自定义5.支持大缓存压缩处理,支持自定义6.支持自定义拦截器的AOP扩展,可以处理参数、返回值、异常快速使用通用接入1.maven(因域名问题,暂没有上传中央仓库),可以下载源码install到本地或者上传到私服,也可以先下载jar     org.plume     plumecache-core     1.0.0  复制代码2.配置plumecache:   instances:     - type: redis       endpoint: 127.0.0.1:6379       prefix: order 复制代码3.使用@Test public void test(){         CacheService cacheService=CacheServiceFactory.getInstance();         cacheService.set("name","anson.yin");         System.out.println(cacheService.get("name")); } 复制代码spring boot接入1.maven(因域名问题,暂没有上传中央仓库),可以下载源码install到本地或者上传到私服,也可以先下载jar      org.plume     plumecache-spring-boot-starter     1.0.0  复制代码2.配置plumecache:   instances:     - type: redis       endpoint: 127.0.0.1:6379       prefix: order 复制代码3.使用@Autowired private CacheService cacheService;  @RequestMapping(value = "/hello") public String hello(){         cacheService.set("name","anson.yin");         return"hello,".concat(cacheService.get("name")); } 复制代码功能说明配置plumecache:   instances:     - type: redis #必填       name: redis #非必填,缺省为和type一样       endpoint: 127.0.0.1:6379  #必填       prefix: order #非必填,like "prefix@key"       serializer: org.plumecache.samples.FastjsonCacheSerializer  #非必填,指定序列化类,缺省使用Gson序列化       compressor: org.plumecache.samples.NoneCacheCompressor  #非必填,指定压缩类,缺省使用Gzip压缩       exclude-interceptors: SlowCacheInterceptor,LogCacheInterceptor #非必填,排除不需要的拦截器 复制代码多实例
  配置plumecache:   instances:     - type: redis #必填       name: redis #非必填,缺省为和type一样       endpoint: 127.0.0.1:6379  #必填       prefix: order #非必填,like "prefix@key"       serializer: org.plumecache.samples.FastjsonCacheSerializer  #非必填,指定序列化类,缺省使用Gson序列化       compressor: org.plumecache.samples.NoneCacheCompressor  #非必填,指定压缩类,缺省使用Gzip压缩       exclude-interceptors: SlowCacheInterceptor,LogCacheInterceptor #非必填,排除不需要的拦截器     - type: memcached       endpoint: 127.0.0.1:11211     - type: memcached       name: memcached2       endpoint: 127.0.0.1:11222     - type: rediscluster       endpoint: 127.0.0.1:6379,127.0.0.1:6389,127.0.0.1:6399 复制代码
  说明0.上面的配置了四个缓存实例1.默认的缓存实例是第一个配置2.同一种类型多个实例,需要配置不同name来区分
  代码示例@Test public void testMultipleInstances() {         //和CacheService redis =CacheServiceFactory.getInstance("redis")效果一样         CacheService redis = CacheServiceFactory.getInstance();         redis.set("instance", "redis");         System.out.println(redis.get("instance"));          CacheService memcached = CacheServiceFactory.getInstance("memcached");         memcached.set("instance", "memcached");         System.out.println(memcached.get("instance")); } 复制代码序列化1.默认使用Gson作为序列化2.自定义序列化,需要实现CacheSerializer接口,并且在配置配置序列化类
  下面是FastjsonCacheSerializer的实现示例public class FastjsonCacheSerializer implements CacheSerializer {      @Override     public  String serialize(T value) {         return JSON.toJSONString(value);     }      @Override     public  T deserialize(String value, Class clazz) {         return JSON.parseObject(value, clazz);     } } 复制代码缓存压缩1.实体类添加 @CacheCompress 注解@Data @CacheCompress public class User {     private String name;     private Integer age;     private String address; } 复制代码2.调用方式不变    @Test     public void testCompress() {         User user = new User();         user.setAge(100);         user.setName("zhangsanfeng");         user.setAddress("zhangsanfengzhangsanfengzhangsanfengzhangsanfengzhangsanfengzhangsanfengzhangsanfengzhangsanfengzhangsanfengzhangsanfengzhangsanfeng");          cacheService.set("user", user);         User cacheUser = cacheService.get("user", User.class);                  System.out.println(cacheUser);     } 复制代码127.0.0.1:6379> get order@user " >]H4sIAAAAAAAAAKtWSkxJKUotLlayUqrKSMxLL07MS0vNSx8otpKOUmJ6qpKVoYGBjlJeYm4qmruU agHJDU9isgAAAA==" 复制代码3.自定义压缩器
  默认使用gzip压缩,也可以自定义实现,且添加配置
  参考GzipCacheCompressor.java缓存版本1.实体类添加 @CacheVersion 注解@Data @CacheVersion("2.0") public class User {     private String name;     private Integer age;     private String address; } 复制代码2.调用方式不变    @Test     public void testVersion() {         User user = new User();         user.setAge(100);         user.setName("zhangsanfeng");         user.setAddress("address");          cacheService.set("user", user);         User cacheUser = cacheService.get("user", User.class);          System.out.println(cacheUser);     } 复制代码127.0.0.1:6379> get order@user@2.0 " >5{"name":"zhangsanfeng","age":100,"address":"address"}" 复制代码拦截器
  拦截器是对缓存操作的切面处理,自定义拦截器操作如下1.实现CacheInterceptor,或者继承BaseCacheInterceptor,举例如下@Slf4j public class SlowCacheInterceptor extends BaseCacheInterceptor {      @Override     public boolean preHandle(CacheService target, Method method, Object[] args, Map context) {         Instant begin = Instant.now();         context.put("SlowCacheInstantBegin", begin);         return true;     }      @Override     public void postHandle(CacheService target, Method method, Object[] args, Map context, Object result) {         Instant begin = (Instant) context.get("SlowCacheInstantBegin");          if (Duration.between(begin, Instant.now()).toMillis() > 500) {             log.warn("[SlowCacheInterceptor]slow cache, method:{},args:{},result:{},cost:{}"                     , method.getDeclaringClass().getName() + "." + method.getName()                     , JSON.toJSONString(args)                     , JSON.toJSONString(result)                     , Duration.between(begin, Instant.now()).toMillis());              //do something others         }     } } 复制代码2.添加SPI的配置
  path:resources/services/com.plumecache.core.interceptor.CacheInterceptororg.plumecache.samples.SlowCacheInterceptor 复制代码
  或者参考core包实现LogCacheInterceptor.javaVersionCacheInterceptor.javaPrefixCacheInterceptor.java管理接口
  在spring boot stater且为web项目时生效1.list 显示实例列表curl -X GET localhost:8080/plumecache/list 复制代码[{"properties":{"name":"memcached","type":"memcached","endpoint":"127.0.0.1:11211","prefix":null,"serializer":null,"compressor":null,"excludeInterceptors":null},"statistics":{"cmd_touch":"0","moves_to_cold":"5","incr_hits":"1","get_flushed":"0","evictions":"0","touch_hits":"0","expired_unfetched":"0","pid":"1","time_in_listen_disabled_us":"0","response_obj_bytes":"65536","cas_badval":"0","cmd_flush":"0","total_items":"6","read_buf_oom":"0","round_robin_fallback":"0","slab_reassign_rescues":"0","log_watcher_skipped":"0","cas_hits":"0","accepting_conns":"1","auth_errors":"0","slab_reassign_evictions_nomem":"0","log_watcher_sent":"0","reserved_fds":"20","slab_reassign_running":"0","response_obj_oom":"0","crawler_items_checked":"12","direct_reclaims":"0","conn_yields":"0","slab_reassign_busy_deletes":"0","version":"1.6.10","read_buf_count":"8","listen_disabled_num":"0","slab_global_page_pool":"0","get_misses":"0","hash_is_expanding":"0","touch_misses":"0","get_expired":"0","auth_cmds":"0","cas_misses":"0","delete_misses":"0","cmd_meta":"0","get_hits":"4","slab_reassign_inline_reclaim":"0","malloc_fails":"0","delete_hits":"0","log_worker_written":"0","read_buf_bytes_free":"49152","lru_bumps_dropped":"0","curr_connections":"2","bytes_written":"4650","slab_reassign_busy_items":"0","hash_bytes":"524288","libevent":"2.1.8-stable","read_buf_bytes":"131072","lrutail_reflocked":"0","crawler_reclaimed":"0","decr_hits":"0","limit_maxbytes":"67108864","max_connections":"1024","decr_misses":"0","lru_crawler_running":"0","reclaimed":"0","rejected_connections":"0","cmd_get":"4","hash_power_level":"16","curr_items":"3","threads":"4","cmd_set":"5","bytes_read":"360","slab_reassign_chunk_rescues":"0","lru_crawler_starts":"27","uptime":"22253","log_worker_dropped":"0","unexpected_napi_ids":"0","total_connections":"9","evicted_active":"0","incr_misses":"1","connection_structures":"4","bytes":"221","lru_maintainer_juggles":"30247","evicted_unfetched":"0","rusage_system":"12.600134","time":"1638171110","slabs_moved":"0","moves_within_lru":"0","pointer_size":"64","moves_to_warm":"0","rusage_user":"8.090528","response_obj_count":"1"}},{"properties":{"name":"redis","type":"redis","endpoint":"127.0.0.1:6379","prefix":"order","serializer":"org.plumecache.samples.FastjsonCacheSerializer","compressor":"com.plumecache.core.compressor.NoneCacheCompressor","excludeInterceptors":["SlowCacheInterceptor","LogCacheInterceptor"]},"statistics":{"io_threaded_reads_processed":"0","tracking_clients":"0","uptime_in_seconds":"22224","cluster_connections":"0","current_cow_size":"0","maxmemory_human":"0B","aof_last_cow_size":"0","master_replid2":"0000000000000000000000000000000000000000","mem_replication_backlog":"0","aof_rewrite_scheduled":"0","total_net_input_bytes":"19507","rss_overhead_ratio":"1.58","hz":"10","current_cow_size_age":"0","redis_build_id":"69ab6eec4665acbc","aof_last_bgrewrite_status":"ok","multiplexing_api":"epoll","client_recent_max_output_buffer":"0","allocator_resident":"5181440","mem_fragmentation_bytes":"6549960","repl_backlog_first_byte_offset":"0","tracking_total_prefixes":"0","redis_mode":"standalone","cmdstat_get":"calls=10,usec=342,usec_per_call=34.20,rejected_calls=0,failed_calls=0","redis_git_dirty":"0","allocator_rss_bytes":"3031040","repl_backlog_histlen":"0","io_threads_active":"0","rss_overhead_bytes":"2990080","total_system_memory":"2082197504","loading":"0","evicted_keys":"0","maxclients":"10000","cmdstat_set":"calls=10,usec=1941,usec_per_call=194.10,rejected_calls=0,failed_calls=0","cluster_enabled":"0","redis_version":"6.2.5","repl_backlog_active":"0","mem_aof_buffer":"0","allocator_frag_bytes":"447160","io_threaded_writes_processed":"0","instantaneous_ops_per_sec":"0","used_memory_human":"1.59M","cmdstat_incr":"calls=1,usec=68,usec_per_call=68.00,rejected_calls=0,failed_calls=0","total_error_replies":"0","role":"master","maxmemory":"0","used_memory_lua":"37888","rdb_current_bgsave_time_sec":"-1","used_memory_startup":"809880","used_cpu_sys_main_thread":"146.683765","lazyfree_pending_objects":"0","used_memory_dataset_perc":"38.70%","allocator_frag_ratio":"1.26","arch_bits":"64","used_cpu_user_main_thread":"38.482678","mem_clients_normal":"512400","expired_time_cap_reached_count":"0","unexpected_error_replies":"0","mem_fragmentation_ratio":"5.04","aof_last_rewrite_time_sec":"-1","master_replid":"9c1aa9fc501b889e35727910956569cac1a2fda1","aof_rewrite_in_progress":"0","lru_clock":"10781132","maxmemory_policy":"noeviction","run_id":"d05aa7e4384c6ccd09ee83e919c9e9edcd2d8450","latest_fork_usec":"439","tracking_total_items":"0","total_commands_processed":"1349","expired_keys":"0","used_memory":"1664360","module_fork_in_progress":"0","dump_payload_sanitizations":"0","mem_clients_slaves":"0","keyspace_misses":"3","server_time_usec":"1638171084987972","executable":"/data/redis-server","lazyfreed_objects":"0","db0":"keys=232,expires=0,avg_ttl=0","used_memory_peak_human":"4.53M","keyspace_hits":"7","rdb_last_cow_size":"520192","used_memory_overhead":"1333640","active_defrag_hits":"0","tcp_port":"6379","uptime_in_days":"0","used_memory_peak_perc":"35.03%","current_save_keys_processed":"0","blocked_clients":"0","total_reads_processed":"1900","expire_cycle_cpu_milliseconds":"7066","sync_partial_err":"0","used_memory_scripts_human":"0B","aof_current_rewrite_time_sec":"-1","aof_enabled":"0","process_supervised":"no","cmdstat_info":"calls=2,usec=559,usec_per_call=279.50,rejected_calls=0,failed_calls=0","master_repl_offset":"0","used_memory_dataset":"330720","used_cpu_user":"38.497928","rdb_last_bgsave_status":"ok","tracking_total_keys":"0","cmdstat_ping":"calls=1325,usec=19580,usec_per_call=14.78,rejected_calls=0,failed_calls=0","atomicvar_api":"c11-builtin","allocator_rss_ratio":"2.41","client_recent_max_input_buffer":"16","clients_in_timeout_table":"0","aof_last_write_status":"ok","mem_allocator":"jemalloc-5.1.0","cmdstat_incrby":"calls=1,usec=21,usec_per_call=21.00,rejected_calls=0,failed_calls=0","used_memory_scripts":"0","used_memory_peak":"4751720","process_id":"1","master_failover_state":"no-failover","used_cpu_sys":"146.736539","repl_backlog_size":"1048576","connected_slaves":"0","current_save_keys_total":"0","gcc_version":"8.3.0","total_system_memory_human":"1.94G","sync_full":"0","connected_clients":"25","module_fork_last_cow_size":"0","total_writes_processed":"1349","allocator_active":"2150400","total_net_output_bytes":"18709","pubsub_channels":"0","current_fork_perc":"0.00","active_defrag_key_hits":"0","rdb_changes_since_last_save":"0","instantaneous_input_kbps":"0.00","configured_hz":"10","used_memory_rss_human":"7.79M","expired_stale_perc":"0.00","active_defrag_misses":"0","used_cpu_sys_children":"0.029570","number_of_cached_scripts":"0","sync_partial_ok":"0","used_memory_lua_human":"37.00K","rdb_last_save_time":"1638169845","pubsub_patterns":"0","slave_expires_tracked_keys":"0","redis_git_sha1":"00000000","used_memory_rss":"8171520","rdb_last_bgsave_time_sec":"0","os":"Linux 5.10.47-linuxkit x86_64","mem_not_counted_for_evict":"0","active_defrag_running":"0","rejected_connections":"0","total_forks":"3","active_defrag_key_misses":"0","allocator_allocated":"1703240","instantaneous_output_kbps":"0.00","second_repl_offset":"-1","rdb_bgsave_in_progress":"0","used_cpu_user_children":"0.012939","total_connections_received":"575","migrate_cached_sockets":"0"}}] 复制代码2.execute 执行缓存操作curl localhost:8080/plumecache/execute  -X POST  -H "Content-Type: application/json"  -d "{"command":"get","key":"name"}" 复制代码anson.yin 复制代码接口说明
  参考CacheService.javaRoadMap
  version 1.0.01.支持spring boot 项目接入, 基于spring boot starter和 enable 以及 conditional注解完成初始化 --done2.支持spring项目介入 提供初始化工具类 --done3.支持key前缀功能 --done4.支持多个cache实例 --done5.支持get、set、delete、exists、expire、ttl命令 --done6.支持dashboard api(实例列表,实例参数,命令执行)7.支持自定义拦截器 --done8.支持自定义序列化 --done9.返回具体实例(redissonclient、MemcachedClient)对象 --done10.实现hget,hset,hgetall,lock 命令 --done11.支持缓存压缩功能(大value压缩) --done12.支持版本功能(version 注解) --done
  version 2.0.00.缓存参数配置(timeout,poolsize,idlecount,attempts)1.支持线程内缓存(基于threadlocal)2.支持字段序列化(基于ObjectOutputStream)项目结构
  作者:广陵笑笑生
  链接:https://juejin.cn/post/7038850628965105672

2021年家用吸尘器哪个牌子好?扫把和簸箕,在中华文明上下五千年的历史中一直扮演着一个很重要的角色,而当时间来到现代,这种老旧且效率较低的清扫方式就会让人感觉到诸多不便。地面上的落灰,必须用柔和的力气慢慢打扫,否今年双11不用定闹钟!京东天猫晚8点即可开抢9月18日,资本邦了解到,今年双11玩法已经迫不及待的剧透了一波。往年,双十一的晚上,万家灯火通明,部分消费者定好闹钟在等12点好清空购物车。今年,大家终于不再熬夜抢购了,京东天猫广电总局要求停止宣传推销槟榔及制品iPhone13秒没苹果官网崩溃今日头条1。微信聊天将可访问外链,在保证安全的情况下更好地实现互联互通9月17日,腾讯对外公布关于互联互通第一阶段进展。腾讯表示,自9月17日起,用户升级最新版本微信后,可以在一对阿里健康大药房开通24小时执业药师咨询中国青年报客户端讯(中青报中青网记者王聪聪)夜间孩子发烧怎么用药?盐酸氨基葡萄糖,70岁老人睡前吃几粒?孩子晚上老起湿疹,为什么用药没效果?为了更好满足用户夜间用药需求,阿里健康大扒一扒阿里商业帝国现金流到底有多么的恐怖?今天我们按照天猫商城的入驻保证金标准来计算,入驻天猫保证金旗舰店10万专营店15万专卖店5万再看一下三种类型的店铺各有多少家旗舰店总计395280家(三十九万五千二百八十)专营店总看华为血压手表,悟华为商业模式送给父母给长辈最好的礼物是什么呢?是钱吗?不是!是健康!相信不久的将来,过节不收礼,收礼收健康,会成为健康送礼的一种形式。那送什么呢?程哥推荐你一款见了,你见了绝对会喜欢的一款产品挑选家用监控摄像头如何选焦距,选多少合适摄像机镜头的焦距指的是镜片中心到成像传感器的距离,焦距代表着看到的视角。一般而言,焦距越小的话,角度也就越大。焦距越大,代表可以把远处的景物拉近,使主体在画面上成像大,表现出细节,互联网平台围墙花园破拆进行时私域业态早已商机涌动经济观察网记者钱玉娟作为苏州魔方互动网络科技有限公司的创始人兼CEO,杨阳在过去的一个月里见了很多家投资机构,他充分感受到自己所在的私域营销这个细分赛道热了起来。就在接受经济观察报240多家平台围剿滴滴,破局之道在哪里?面对同行围剿和合规风险,滴滴四面楚歌,Robotaxi能助其脱离困境,还是将它推向深渊?文东篱网约车从来不是一个有宽大护城河的行业。9月17日,交通运输部发布消息称,据全国网约车监买不到华为,只能买苹果,这场持续50年的供应链阴谋发挥作用了?天下熙熙,皆为利来天下攘攘,皆为利往。苹果iPhone13如约而至,今年的宣传方向是苹果不仅配置升级还降价了。这个点选得不错,直接击中消费者的命门,为其在各平台赢得上千万的预订人数谁说千元机配置都很差?这三款表示不服,完美适合学生党以前安卓系统还没有发展起来,流畅度什么的比iPhone要差,特别是千元机更为明显,不少用户都被坑过,也把这个刻板印象带到现在,但其实安卓手机的配置已经跟上,甚至某些方面超越了iPh
米家多款新品齐亮相旗舰配置售价良心近日,米家发布多款新品,包括扫拖机器人无线吸尘器即热净水器等。其中米家扫拖机器人2Pro支持电解水杀菌,在水箱内置了专业的电解水装置,将自来水电解成杀菌水,拖除脏污的同时还能进行杀下跌三千多,发布一年如今濒临下架,12GB512GB手机市场随着科技发展与社会发展的双重推动下,产品也都开始五花八门的种类越来越多了。在手机市场上的产品越来越多了之后啊,厂商对于手机的外观也是越做越好看了,但是其实有一个特定的发展方腾讯网易纷纷放弃独家音乐版权,能听歌自由了吗音乐的版权之争拉锯战可以追溯到很久之前,那么下面就按近几年的音乐版权之争开始理一理音乐版权的路线。音乐平台事实上,版权费用的飙升早有迹可循。2015年7月8日,国家版权局下发了关于GitHub已标星93K!网易首席架构师闭关3月撰写1200页网络协议笔记网络协议介绍网络协议为计算机网络中进行数据交换而建立的规则标准或约定的集合。网络协议网络协议指的是计算机网络中互相通信的对等实体之间交换信息时所必须遵守的规则的集合。对等实体通常是特斯拉新跑车Roadster2快交付了,希望能够注重使用安全特斯拉CEO马斯克最近在社交网站上透露,2021是供应链超级短缺到疯的一年,所以如果我们有17个新产品也没关系,因为没有一个能交付。假如2022年不发生戏剧性事件,Roadster淘宝的slogan变了,蓄谋已久?又会给你带来什么新的体验?细心的淘友可能已经看到了,淘宝的开屏页已经换新了。现在的就不太一样了。之前的淘宝盒子被搬到了屏幕中间,下面配了一行剪短的文字太好逛了吧!淘宝作为比较大的电商平台,从好用到好逛,说明9月3日北汽新能源净亏14亿恒驰7路试观致月产0小鹏取消大小周北汽新能源2021年上半年净亏损14。09亿元据三言财经报道,9月2日消息,北京新能源汽车股份有限公司公告称,2021年16月,公司净亏损14。09亿元2020年末,公司净资产10阿里最大股东是日企,腾讯背后是南非,小米京东有没有沦陷?阿里巴巴和腾讯是中国最大的两个互联网巨头,前者在生活方式上带来了巨大的改革,后者改变了人们的娱乐以及社交方式。能成为一个行业的尖端,身价自然也是不菲的。阿里巴巴巅峰时期市值为800曲面屏轻薄机身65W闪充,12GB256GB旗舰跌至2299元前有OLED和LCD屏幕之争,很多网友呼吁LCD永不为奴,现有曲面屏和直屏之争!很多网友吐槽曲面屏花里胡哨,没有太大的用处,还容易误触,没有直屏体验那么好,号称以用户体验著称的苹果苹果再次让步,将允许部分应用使用第三方支付日前,苹果方面宣布AppStore即将迎来更新,这也意味着日本公平贸易委员会(JFTC)对AppStore的调查宣告结束。据悉,此次更新将允许阅读器类应用的开发者在其APP内提供访传Exynos2200获得2亿颗预购订单,三星推全球首款2亿像素手机图像传感器此前一直有传言指,三年会在6月或7月公开首款搭载AMDRDNA2架构GPU的SoC,也就是Exynos2200,不过迟迟没有到来。有消息指,Exynos2200将使用三星4nmLP