演讲稿
来源:互联网 发布:crf算法 编辑:程序博客网 时间:2024/05/17 09:05
在项目的应用中,我整理出几个解决问题的点出来讲。如果有更好的方案,可以提一下,或是指出哪里不好,我可以改进。
一、【队列和线程池的运用】
我可以运用队列中的阻塞队列和线程池,根据生产者和消息者的模式做这样一件事,一个程序,运行,然后开出10个线程,等这个程序拿到10线程的运行结果后,再接着运行。
【案例】
比如现在有三个用户发了三条短信到10086,短信A=办理套餐A,短信B=查询流量B,短信C=取消业务C,数据保存在表里(叫上行表),状态是未处理。然后定时器读取上行表这三个短信,根据短信内容(叫指令)办理对应的业务后回复结果,并把状态update为成功或失败
普通:单线程,单个更新数据【运行慢,数据库频繁操作,性能低】
for(){============================>差不多运行15s
if(短信内容==办理套餐A){
运行办理套餐A-后发短信(耗时4s),更新状态1s
}else if(短信内容==查询流量B){
运行查询流量B-后发短信(耗时4s),更新状态1s
}else if(短信内容==取消业务C){
运行取消业务C-后发短信(耗时4s),更新状态1s
}
}
优化:开线程池,单个更新数据【运行快点,但数据库频繁操作,性能低】
for(){============================>差不多运行5s
run(线程个数3){
if(短信内容==办理套餐A){
运行办理套餐A-后发短信(耗时4s),更新状态1s
}else if(短信内容==查询流量B){
运行查询流量B-后发短信(耗时4s),更新状态1s
}else if(短信内容==取消业务C){
运行取消业务C-后发短信(耗时4s),更新状态1s
}
}
}
再优化:开线程池,批量更新数据【运行快点,数据库不用频繁操作,性能好些】
for(){============================>差不多运行4s
run(线程池个数设置为3){
if(短信内容==办理套餐A){
运行办理套餐A(耗时4s)-后发短
}else if(短信内容==查询流量B){
运行查询流量B(耗时4s)-后发短信
}else if(短信内容==取消业务C){
运行取消业务C(耗时4s)-后发短信
}
}
}
主线程等拿到3个子线程的结果后,分类成功的,失败的。只要执行2条update语句批量更新(一条成功类,一条失败类的)
【注:这里我们不是用if判断,为了方便了解才用if讲解,当用户短信数量多时,可以调整每交读数据库条数,调整线程池大小,可以一次读取和写入数据库。方法还可运用在其他地方】
【线程池知识点】(这个可不用看)
1.定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
Executor executor = Executors.newFixedThreadPool(3);
2.单线程化的线程池,它只会用唯一的工作线程来执行任务,相当于顺序执行各个任务。
Executor executor = Executors.newSingleThreadExecutor();
3.可缓存线程池,线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
Executor executor = Executors.newCachedThreadPool();
4.定长线程池,支持定时及周期性任务执行。
【队列知识点】(这个可不用看)
1)add(anObject):如果队列可以容纳,则返回true,否则报异常
2)offer(anObject):如果队列可以容纳,则返回true,否则返回false.
3)put(anObject):队列没有空间,则调用此方法的线程被阻断直到队列里面有空间再继续.
4)poll(time):取走队列里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,取不到时返回null
5)take():取走队列里排在首位的对象,若队列为空,阻断进入等待状态直到Blocking有新的对象被加入为止
ArrayBlockingQueue<Object> queue = new ArrayBlockingQueue<Object>(capacity);
queue.put(onQueueListener.put(attr));//生产者
queue.take()//消息者
二、【性能,效率,安全性考虑】
开发时,我一般会做一些性能,效率,安全性方面的考虑。
【导入导出】
我开发时,把导入导出功能做成一个通过中间件,多个模块有导入导出功能时,只要调用一下就可以用。
导出:
比如数据库有1千万数据要导出,我提供一个模块,给用户做参数配置
1.配置数据库一次分页读取多少条数,【防止一次性读到list后,内存溢出或数据量大数据库读取性能不好】
2.配置每个excel可以有多少个sheet,每个sheet可以放多少行。【防止excel数据过多,打不开】
3.导出时,像数据量很大,按配置参数生成后有excelA.xls,excelB.xls,excelC.xls...等,生成多个excel文件。系统会自动压缩成一个压缩文件,供用户下载。【加压缩后少文件下载大小,也方便一次性下载】
4.一般导出不是做成用户一点击导出,然后程序就运行导出。是做成点击导出后,生成一条记录,待定时器去生成,可以看到导出进度,待文件生成成功,再点击下载【防止数据量大时,一直占用一个http连接数,重复导出,浏览器不小心关掉导出中断,可查看导出记录信息,方便再次下载导出文件,无需再生成等等】
导入:同样的原理,可以上传压缩文件导入,程序自动处理导入的压缩文件,生成一条记录,待定时器去导入,【防止重复导入数据,浏览器中断等。】
【提供第三方接口】
第三方接入时,提供接口方接入方标识A,密钥B,用户名name,密码pwd
这里举个列子:第三方把用户名name,密码pwd,其他请求参数通过密钥B加密后当成一个参数p1,再把接入方标识A当成第2个参数p2;然后请求系统
系统解析:系统根据传过来的标识p2即接入方标识A,找到对应的密钥,解密成功后,可以得到所有参数,再通过用户名和密码检验,成功后返回同样方法加密的密文
【上传图片】
用户通过微信上传图片后,程序自动生成不同规格的图片,根据界面展示合理规格的图片,减少用户流量消耗,打开图片久等问题
【起应急和告警机制】
起应急后,程序设计时,对于比较重要的功能,告知用户“当成系统维护中,”
告警机制,程序定时器扫描哪个功能,当系统失败率高时,通过短信等方式通知维护人员。如果担心短信费用问题,这里可以创建个公众号叫告警群,通过客服消息接口下发通知维护人员。
三、【集群的分布式算法】
这个算法可应用于缓存集群,分库,分表等。
【举例】
memcache类似个map,根据key值,存放缓存map.put(key,value),获取缓存map.get(key)
比如现在有三台memcache0,memcache1,memcache2集群,我要把值为valueA存放到三台中的一台,key值为keyA。后面可以通过keyA,从三台缓存中有valueA的一台取出valueA
普通:随机放入,循环取出【集群个数多,取缓存数据每次都要循环,命中率也低】
1.存放数据到缓存中
因为有三台,所以从0-2随机产生一个数,如果随机数为0,把valueA放到memcache0中memcache0.put(keyA,valueA),如果为2,把valueA放到memcache2中memcache2.put(keyA,valueA),以此类推
2.根据keyA取出valueA
for(int i =0;i<3;i++){//循环集群个数【注,这里为了方便了解才用if判断】
if(i == 0){
Value = memcache0.get(keyA);
}else if(i == 1){
Value = memcache1.get(keyA);
}else if(i == 2){
Value = memcache1.get(keyA);
}
If(value != null) return value;
}
优化:求余分散【命中率高,但后期添加第4台集群后,命中率低,如果缓存中共4千万数据,大概有:4千万/集群后个数4*添加个数1=1千万数据没命中,得循环】
1.存放数据到缓存中
通过keyA.hashCode()%集群个数3,计算对应哪台,这里是3台,所以余数落在0-2
例如keyA.hashCode()=8,那8%3=2,则把valueA放到memcache2中memcache2.put(keyA,valueA),以此类推
2.根据keyA取出valueA
因为keyA.hashCode()=8,那8%3=2,所以从memcache2中取memcache2.get(keyA)
再优化:顺时针最近节点的方法【命中率高,后期添加第4台集群后,影响范围小】
1.存放数据到缓存中【注,此方法比按0~232 的哈希值方法分布均匀】
先定一个一般集群个数不会超过的数,比如10万,这里是3台,计算出3台memcache的标识分别为0,33333,66666【如图分布】【这里我自己封装了个工具类,可以根据集群个数,自动生成下标,后期添加集群也可以通过工具类自动算出来】:
。通过【keyA.hashCode()%100000(一般集群不过超过10万)】计算,因为keyA.hashCode()=8 ,那8%100000=8,然后8的位置开始顺时针(存放或取)数据,依次为33333(memcache1),66666(memcache2),0(memcache0),最近有一台memcache1,如果保放失败/取不到值,再顺时针最近有一台memcache2,如果还是不行,再继续顺时针找,找到memcache0,以些类推。
添加第4台,memcache3后,取圆中最长的线段,平均一下,0,33333,66666,83333【如图分布】,影响范围为添加节点到逆时针的一个节点,即虚线部分。【如果缓存中共4千万数据,大概有:4千万/第一次集群个数3/(2的后期所有添加台数1的次方)=6百6十6万数据没命中,影响范围少了,随着集群个添多,分布越均匀】
分库分表也可以运用这个算法,如有一个用户表,用户预期3亿,那准备3张表存放,可以根据用户id=keyA,存放valueA=用户信息到这3张表中的1张,后期根据ID更新删除查询时,可根据计算去对应的表操作,
四、【高并发的抢购类活动】
这个是根据2016年支付宝抢红包原理方案做的。
主要原理:
1.例如,一台服务器64G内存,一个tomcat最大连接数是200,现在并发1千个用户请求,单纯用一台服务器一个tomcat,这时有1千-200=800个用户处于等待状态,高并发后,面对短时间内抢购压力,连接数远远不够,造成了一个访问瓶颈。现在采用nginx负载均衡两台服务器,搭建10个tomcat后,相当于拥有200*10=1千个连接数,64*2=128G内存处理量。并发1千个用户请求后,接近无等待请求。消除访问瓶颈。
2.
开始抢购商品,一个表A有个商品iphone记录,id=1,剩余数量num=1千万。抢购开始后,每个用户都要更新这条记录update A set num=num-1 where num >0 ,抢购iphone的用户都要更新这条记录。
更新同个记录,一个用户update花0.01s,1万个用户就得花100秒,相当于一个用户点击抢购后,100秒才能运行完,短时间内,数据库更新成了一个瓶颈,而且高并发下,数据库性能急巨下降,数据库连接池也有限,不只100秒。
现在我们采用分库分表,两人个数据库共创建10张表(id=1,剩余数量num=100万,10张表数量之和为1千万,与原来一样),5张表放到数据库A,5张表放到数据库B。1万个用户并发抢购,原本1张表1个库处理,现在改为10张表,2个库处理,相当于开出10个池程同时更新。1万个用户原先花100秒,现在10秒左右运行完成。
【这里采用上面讲的分布式算法来讲解,这里简略说一下。】
用户ID为keyA进来抢购。
keyA.hashCode()=8,那8%10万=8,假定10张表静态缓存ListA={0,1,2,3...9},根据listA顺时针排列后放到listB中,listB=>{8,9,0,1,2,3,4,5,6,7}
boolean update_ok = false; //是否抢购到商品
for(listB){
影响行u = update A(根据标识更新对应表) set num=num-1 where num >0
if(u >0){//更新成功
update_ok = true;
break;
}else{//说明当前表数量为0
ListA.remove(当前表)//方便下一用户知道此表已经没数量,无需再操作
}
}
If(update_ok == true){抢购成功}else{已经抢完}
这个是数量扣减,支付宝抢红包是全额扣减,就得多一步碎片合并的机制。当10张表中有一张数量为0,就触发其余数量不为0的张合并。统一到一张表进行抢购。
【这里说一下显示问题,10张表在不断抢购时,要显示总的剩余数量】
采用队列和线程池,主线程开出10个线程分别查询10张剩余数量,等主程序拿到10线程的查询结果后,再将所有数量相加显示。
3.通过内存和缓存,把可缓存的数据缓存起来,减少对数据库的操作,提高效率和数据库性能。
- 演讲稿
- 演讲稿
- 演讲稿写作与演讲艺术(摘抄)
- Nash演讲稿中文版
- 公司晚会演讲稿
- 日语演讲稿
- shell 演讲稿
- 今晚的演讲稿
- 科协就职演讲稿
- 演讲稿开场白
- Speechwriting 演讲稿写作
- 马云演讲稿
- 长征精神演讲稿
- 演讲
- 演讲
- 演讲
- 演讲
- 演讲
- Android webview,js,属性
- Mac版MySQL修改初始密码
- 基于POSIX下REGEX库的文本URL过滤(C/C++语言)
- Intel CPU 地址空间总结
- 读《灵魂只能独行》乱摘
- 演讲稿
- linux中ssh使用rsa免密码登录方法
- python开发环境搭建 (eclipse)
- vim常用命令总结
- MySQ的列类型的选择原则
- 获取偶数位和奇数位并输出二进制序列,采用右移符>>。
- Gem5安装教程
- 推荐系统-笔记(下)
- maven项目部署到Repository(Nexus)