Redis

用多线程优化Excel表格数据导入校验的接口

爱⌒轻易说出口 提交于 2021-02-18 05:35:28
公司的需求,当前某个Excel导入功能,流程是:读取Excel数据,传入后台校验每一条数据,判断是否符合导入要求,返回给前端,导入预览展示。(前端等待响应,难点)。用户再点击导入按钮,进行异步导入(前端不等待,好做)。当前接口仅支持300条数据,现在要求我要支持3000条数据。 解决问题,思路是关键。 首先,查看接口,找到读取表格的位置,看到判断,如果数据量大于300,直接返回。把300改成3000. 然后,分析导入数据校验,都是和哪些数据进行校验的,这些数据都是从数据库来的。每一次都从数据库查询,那肯定是慢的。就算是查询Redis缓存,也要有网络消耗,增加缓存的压力。虽然单机Redis有12万次/秒的查询性能,12万除以3000得40,如果这样玩,40个人使用就拖垮系统了。同一个数据,非要查3000次,那是不是傻???所以减少每一次的查询,把数据库查询都加上Redis缓存,把Redis缓存查到的数据,在方法中创建并发安全容器ConcurrentHashMap存储数据,避免重复的查询操作,只查一次直到方法调用结束。 Map<String, Object> map = new ConcurrentHashMap(); Object obj = map.get("key" ); if ( null == obj){ // 查询缓存,或者数据库 String value = "数据" ;

为什么 Redis 要比 Memcached 更火?

混江龙づ霸主 提交于 2021-02-18 04:06:32
作者:Kaito 链接:kaito-kidd.com/2020/06/28/redis-vs-memcached/ 前言 我们都知道,Redis和Memcached都是内存数据库,它们的访问速度非常之快。但我们在开发过程中,这两个内存数据库,我们到底要如何选择呢?它们的优劣都有哪些? 为什么现在看Redis要比Memcached更火一些? 这篇文章,我们就从各个方面来对比这两个内存数据库的差异,方便你在使用时,做出最符合业务需要的选择。 要分析它们的区别,主要从以下几个方面对比: 线程模型 数据结构 淘汰策略 管道与 事务 持久化 高可用 集群化 线程模型 要说性能,必须要分析它们的服务模型。 Memcached处理请求采用多线程模型,并且基于IO多路复用技术,主线程接收到请求后,分发给子线程处理。 这样做好的好处是,当某个请求处理比较耗时,不会影响到其他请求的处理。 当然,缺点是CPU的多线程切换必然存在性能损耗,同时,多线程在访问共享资源时必然要加锁,也会在一定程度上降低性能。 Redis同样采用IO多路复用技术,但它处理请求采用是单线程模型,从接收请求到处理数据都在一个线程中完成。 这意味着使用Redis,一旦某个请求处理耗时比较长,那么整个Redis就会阻塞住,直到这个请求处理完成后返回,才能处理下一个请求,使用Redis时一定要避免复杂的耗时操作。 单线程的好处是

什么是缓存穿透、缓存击穿、缓存雪崩?如何预防?

*爱你&永不变心* 提交于 2021-02-18 02:20:24
一、什么是缓存穿透,如何预防? 缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,请求直接打在了数据库上。 对于缓存穿透的话一般来说只需要针对空值缓存就行,过期时间设置5-10分钟,这样就流量就不会打在数据库上导致死机宕机。 二、什么是缓存击穿,如何预防? 缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。 缓存击穿的话,设置热点数据永远不过期。或者加上互斥锁就能搞定了。 二、什么是缓存雪崩,如何预防? 缓存雪崩,是指在某一个时间段,缓存集中过期失效。 雪崩其实也可以做到提前预防,那就是用到过期时间的key,时间全部错开,此外,有些数据可以做永久保存的话那就直接保存好了,这样就不会造成大面积的key失效了。 1.永不过期 比如某些热点数据可以设置永不过期。 2.过期时间错开 处理缓存雪崩简单,在批量往Redis存数据的时候,把每个Key的失效时间都加个随机值就好了,这样可以保证数据不会在同一时间大面积失效。 如果Redis是集群部署,将热点数据均匀分布在不同的Redis库中也能避免全部失效的问题。 setRedis(Key,value,time + Math.random() * 10000) 3.多缓存结合

python笔试题

夙愿已清 提交于 2021-02-18 01:50:39
1、python中is和==的区别 A.Python中对象包含的三个基本要素,分别是:id(身份标识) 、type(数据类型)和value(值)。 B.‘==’比较的是value值 C.‘is’比较的是id 2、简述read、readline、readlines的区别 read读取整个文件 readline读取下一行数据 readlines读取整个文件到一个迭代器以供我们遍历(读取 到一个list中,以供使用,比较方便) 3、举例说明创建字典的至少两种方法 # 1 dict1 = {key1:v1,key2:v2} # 2 dict2 = {} dict2[key1] = v1 dict2[key2] = v2 # 3 dict3 = dict(key1=v1,key2=v2) 4、*args,**kwargs的作用是什么?如何使用? *args和**kwargs通常使用在函数定义里,*args允许函数传入不定量个数的非关键字参数,**kwargs允许函数传入不定量个数的关键字参数 5、python中match()和search()的区别? match()函数只检测RE是不是在string的开始位置匹配, search()会扫描整个string查找匹配, 也就是说match()只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回none 6

guava、caffeine、ohc(堆外缓存)详解

笑着哭i 提交于 2021-02-18 01:25:19
一、Guava缓存 Guava Cache适用于以下场景: 你愿意消耗一些内存空间来提升速度。 你预料到某些键会被查询一次以上。 缓存中存放的数据总量不会超出内存容量。(Guava Cache是单个应用运行时的本地缓存。它不把数据存放到文件或外部服务器。如果这不符合你的需求,请尝试Redis这类工具) 仓库坐标如下: <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>19.0</version> </dependency> 代码详细示例: @Data public class CacheVO { private String name; public CacheVO(String name) { this.name = name; } } public class GuavaCacheMangerService { private static LoadingCache<String, CacheVO> cache; private static ExecutorService executorService = new ThreadPoolExecutor(8, 8, 8, TimeUnit.SECONDS, new

使用Canal实现redis和mysql的同步

ⅰ亾dé卋堺 提交于 2021-02-17 22:18:07
使用Canal实现redis和mysql的同步 canal 工作思路 Canal 会将自己伪装成 MySQL 从节点(Slave),并从主节点(Master)获取 Binlog,解析和贮存后供下游消费端使用。Canal 包含两个组成部分:服务端和客户端。服务端负责连接至不同的 MySQL 实例,并为每个实例维护一个事件消息队列;客户端则可以订阅这些队列中的数据变更事件,处理并存储到数据仓库中。下面我们将mysql同步到 redis mysql版本 5.6 canal版本 1.1.0 安装 mysql 后修改自己mysql配置 vim /etc/my.cnf # 开启mysql的binlog模块 log-bin=mysql-bin binlog-format=ROW # server_id需保证唯一,不能和canal的slaveId重复 server_id=121 # 需要同步的数据库名称 binlog-do-db=test_canal # 忽略的数据库,建议填写 binlog-ignore-db=mysql # 启动mysql时不启动grant-tables授权表 skip-grant-tables 创建一个mysql用户 canal 并且赋远程链接权限权限,和测试库 test_canal , CREATE USER canal IDENTIFIED BY 'canal';

Redis(三)--- Redis的五大数据类型的底层实现

被刻印的时光 ゝ 提交于 2021-02-17 20:17:36
1、简介 Redis的五大数据类型也称五大数据对象;前面介绍过6大数据结构,Redis并没有直接使用这些结构来实现键值对数据库,而是使用这些结构构建了一个对象系统redisObject;这个对象系统包含了五大数据对象,字符串对象(string)、列表对象(list)、哈希对象(hash)、集合(set)对象和有序集合对象(zset);而这五大对象的底层数据编码可以用命令OBJECT ENCODING来进行查看。 redisObject结构 1 typedef struct redisObject { 2 // 类型 3 unsigned type: 4 ; 4 // 编码 5 unsigned encoding: 4 ; 6 // 指向底层实现数据结构的指针 7 void * ptr; 8 // ... 9 } robj; redis是以键值对存储数据的,所以对象又分为键对象和值对象,即存储一个key-value键值对会创建两个对象,键对象和值对象。 键对象总是一个字符串对象,而值对象可以是五大对象中的任意一种。 type属性存储的是对象的类型,也就是我们说的 string、list、hash、set、zset中的一种,可以使用命令 TYPE key 来查看。 encoding属性记录了队形所使用的编码,即这个对象底层使用哪种数据结构实现。

Redis系列三

穿精又带淫゛_ 提交于 2021-02-17 18:58:39
前言   从学校出来,做开发工作也有一定时间了,最近有想系统地进一步深入学习,但发现基础知识不够扎实,故此来回顾基础知识,进一步巩固、加深印象。   最初开始接触编程时,总是自己跌跌撞撞、不断摸索地去学习,再一点点应用到实际项目中,知识点才更加清晰。后来,尝试写博客,把学到的知识试着分享出来,也是一次巩固的过程。 1、问:Redis雪崩了解吗?   答:我了解的。目前电商首页以及热点数据都会去做缓存,一般缓存都是定时任务去刷新,或者是查不到之后去更新,定时任务刷新就有一个问题。   举个简单例子:如果所有首页的key失效时间都是12小时,中午12点刷新,我0点开始抢单活动,大量用户涌入,假设当时每秒6000个请求,本来缓存可以扛住每秒5000个请求,但是缓存当时所有的 Key 都失效了。此时,1秒 6000个请求全部打到数据库,数据库必然扛不住,它会报一下警,但实际情况可能是DBA都没反应过来数据库就直接挂了。此时,如果没有什么特别的方案来处理这个故障,DBA很着急,重启数据库,但是数据库马上又被新的流量打死了。这就是我理解的缓存雪崩。    同一时间缓存大面积失效,那一瞬间Redis跟没有一样,这个数量界别的请求直接打到数据库几乎是灾难性的。试想一下,如果打挂的是一个用户服务的库,那其他依赖它的库所有的接口几乎都会报错,如果没有做熔断等策略,基本上就是一瞬间挂一片的节奏

Java分布式锁

独自空忆成欢 提交于 2021-02-17 16:50:56
分布式锁简述 在单机时代,虽然不存在分布式锁,但也会面临资源互斥的情况,只不过在单机的情况下,如果有多个线程要同时访问某个共享资源的时候,我们可以采用线程间加锁的机制,即当某个线程获取到这个资源后,就需要对这个资源进行加锁,当使用完资源之后,再解锁,其它线程就可以接着使用了。例如,在JAVA中,甚至专门提供了一些处理锁机制的一些API(synchronize/Lock等)。 但是到了分布式系统的时代,这种线程之间的锁机制,就没作用了,系统可能会有多份并且部署在不同的机器上,这些资源已经不是在线程之间共享了,而是属于进程之间共享的资源。因此,为了解决这个问题,「分布式锁」就强势登场了。 分布式锁是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中,常常需要协调他们的动作。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,在这种情况下,便需要使用到分布式锁。 在分布式系统中,常常需要协调他们的动作。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,这个时候,便需要使用到分布式锁。 分布式锁要满足哪些要求呢? 排他性:在同一时间只会有一个客户端能获取到锁,其它客户端无法同时获取 避免死锁:这把锁在一段有限的时间之后

Redis事务和分布式锁

雨燕双飞 提交于 2021-02-17 13:08:53
Redis事务   Redis中的事务(transaction)是一组命令的集合。事务同命令一样都是Redis最小的执行单位,一个事务中的命令要么都执行,要么都不执行。Redis事务的实现需要用到 MULTI 和 EXEC 两个命令,事务开始的时候先向Redis服务器发送 MULTI 命令,然后依次发送需要在本次事务中处理的命令,最后再发送 EXEC 命令表示事务命令结束。   举个例子,使用redis-cli连接redis,然后在命令行工具中输入如下命令:     从输出中可以看到,当输入MULTI命令后,服务器返回OK表示事务开始成功,然后依次输入需要在本次事务中执行的所有命令,每次输入一个命令服务器并不会马上执行,而是返回”QUEUED”,这表示命令已经被服务器接受并且暂时保存起来,最后输入EXEC命令后,本次事务中的所有命令才会被依次执行,可以看到最后服务器一次性返回了三个OK,这里返回的结果与发送的命令是按顺序一一对应的,这说明这次事务中的命令全都执行成功了。   再举个例子,在命令行工具中输入如下命令:     和前面的例子一样,先输入MULTI最后输入EXEC表示中间的命令属于一个事务,不同的是中间输入的命令有一个错误(set写成了sett),这样因为有一个错误的命令导致事务中的其他命令都不执行了(通过后续的get命令可以验证),可见事务中的所有命令是同呼吸共命运的。