• [技术干货] 2020-10-26:线程池的线程数怎么设置比较好?
    2020-10-26:线程池的线程数怎么设置比较好?#福大大#
  • [Java] 创建线程的3种方式
    ①. 继承Thread类创建线程类定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。创建Thread子类的实例,即创建了线程对象。调用线程对象的start()方法来启动该线程。②. 通过Runnable接口创建线程类定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。调用线程对象的start()方法来启动该线程。③. 通过Callable和Future创建线程创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。使用FutureTask对象作为Thread对象的target创建并启动新线程。调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。来自:https://zhuanlan.zhihu.com/p/90026505
  • [技术干货] [转载]Python IO模型之非阻塞IO(non-blocking IO)
    非阻塞IO(non-blocking IO)Linux下,可以通过设置socket使其变为non-blocking。当对一个non-blocking socket执行读操作时,流程是这个样子:从图中可以看出,当用户进程发出read操作时,如果kernel中的数据还没有准备好,那么它并不会block用户进程,而是立刻返回一个error。从用户进程角度讲 ,它发起一个read操作后,并不需要等待,而是马上就得到了一个结果。用户进程判断结果是一个error时,它就知道数据还没有准备好,于是用户就可以在本次到下次再发起read询问的时间间隔内做其他事情,或者直接再次发送read操作。一旦kernel中的数据准备好了,并且又再次收到了用户进程的system call,那么它马上就将数据拷贝到了用户内存(这一阶段仍然是阻塞的),然后返回。    也就是说非阻塞的recvform系统调用调用之后,进程并没有被阻塞,内核马上返回给进程,如果数据还没准备好,此时会返回一个error。进程在返回之后,可以干点别的事情,然后再发起recvform系统调用。重复上面的过程,循环往复的进行recvform系统调用。这个过程通常被称之为轮询。轮询检查内核数据,直到数据准备好,再拷贝数据到进程,进行数据处理。需要注意,拷贝数据整个过程,进程仍然是属于阻塞的状态。    所以,在非阻塞式IO中,用户进程其实是需要不断的主动询问kernel数据准备好了没有。非阻塞IO实例:#服务端 from socket import * import time s=socket(AF_INET,SOCK_STREAM) s.bind(('127.0.0.1',8080)) s.listen(5) s.setblocking(False) #设置socket的接口为非阻塞 conn_l=[] del_l=[] while True:     try:         conn,addr=s.accept()         conn_l.append(conn)     except BlockingIOError:         print(conn_l)         for conn in conn_l:             try:                 data=conn.recv(1024)                 if not data:                     del_l.append(conn)                     continue                 conn.send(data.upper())             except BlockingIOError:                 pass             except ConnectionResetError:                 del_l.append(conn)         for conn in del_l:             conn_l.remove(conn)             conn.close()         del_l=[] #客户端 from socket import * c=socket(AF_INET,SOCK_STREAM) c.connect(('127.0.0.1',8080)) while True:     msg=input('>>: ')     if not msg:continue     c.send(msg.encode('utf-8'))     data=c.recv(1024)     print(data.decode('utf-8'))但是非阻塞IO模型绝不被推荐。    我们不能否则其优点:能够在等待任务完成的时间里干其他活了(包括提交其他任务,也就是 “后台” 可以有多个任务在“”同时“”执行)。    但是也难掩其缺点:#1. 循环调用recv()将大幅度推高CPU占用率;这也是我们在代码中留一句time.sleep(2)的原因,否则在低配主机下极容易出现卡机情况 #2. 任务完成的响应延迟增大了,因为每过一段时间才去轮询一次read操作,而任务可能在两次轮询之间的任意时间完成。这会导致整体数据吞吐量的降低。此外,在这个方案中recv()更多的是起到检测“操作是否完成”的作用,实际操作系统提供了更为高效的检测“操作是否完成“作用的接口,例如select()多路复用模式,可以一次检测多个连接是否活跃。
  • [Java] 分代垃圾回收器
    分代垃圾回收器分代回收器有两个分区:老生代和新生代,新生代默认的空间占比总空间的 1/3,老生代的默认占比是 2/3。新生代使用的是复制算法,新生代里有 3 个分区:Eden、To Survivor、From Survivor,它们的默认占比是 8:1:1,它的执行流程如下:把 Eden + From Survivor 存活的对象放入 To Survivor 区;清空 Eden 和 From Survivor 分区;From Survivor 和 To Survivor 分区交换,From Survivor 变 To Survivor,To Survivor 变 From Survivor。每次在 From Survivor 到 To Survivor 移动时都存活的对象,年龄就 +1,当年龄到达 15(默认配置是 15)时,升级为老生代。大对象也会直接进入老生代。老生代当空间占用到达某个值之后就会触发全局垃圾收回,一般使用标记整理的执行算法。以上这些循环往复就构成了整个分代垃圾回收的整体执行流程。207. 说一下 jvm 调优的工具?JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,其中最常用的是 jconsole 和 jvisualvm 这两款视图监控工具。jconsole:用于对 JVM 中的内存、线程和类等进行监控;jvisualvm:JDK 自带的全能分析工具,可以分析:内存快照、线程快照、程序死锁、监控内存的变化、gc 变化等。
  • [Java] jvm 的垃圾回收器
     jvm 的垃圾回收器Serial:最早的单线程串行垃圾回收器。Serial Old:Serial 垃圾回收器的老年版本,同样也是单线程的,可以作为 CMS 垃圾回收器的备选预案。ParNew:是 Serial 的多线程版本。Parallel 和 ParNew 收集器类似是多线程的,但 Parallel 是吞吐量优先的收集器,可以牺牲等待时间换取系统的吞吐量。Parallel Old 是 Parallel 老生代版本,Parallel 使用的是复制的内存回收算法,Parallel Old 使用的是标记-整理的内存回收算法。CMS:一种以获得最短停顿时间为目标的收集器,非常适用 B/S 系统。G1:一种兼顾吞吐量和停顿时间的 GC 实现,是 JDK 9 以后的默认 GC 选项。
  • [其他] 【重分布】终止重分布重新运行业务,应用连接报错negative bitmapset member not allowed
    发生版本【GaussDB A】【8.0.0.1】问题描述重分布完成一部分表之后终止数据重分布,重新启动跑批任务,出现如下几种报错现象:1、  应用程序连接数据库报错negative bitmapset member not allowed;2、  Cn频繁core重启,堆栈如下: 3、  Cn日志中有ERROR:invalid coordinator number: -1, NumCoords: 0报错。问题分析重分布完成一部分表之后终止数据重分布,此时集群还处于重分布Y模式下,如果使用JDBC作为客户端连接,且JDBC的URL带schema信息时,数据库中建立连接时没有初始化CN,DN handles信息导致上述三种报错。解决方案实际业务中很难彻底保证无跟表相关的ddl、跟表关联的对象的ddl、函数返回值带表类型的ddl等操作,所以建议使用方案一,最好不要使用方案二。方案一:1、停止重分布进程;1)omm用户登录第一个cn节点;2)找到gs_redis进程并将其kill -9 杀掉ps -ef |grep gs_redis|grep -v grep找到重分布进程pidkill -9 pid 杀掉重分布进程ps -ef |grep gs_redis|grep -v grep确认进程已被kill掉3)连接第一个cn,将数据重分布活跃语句全部终止掉SELECT pg_terminate_backend(pid);2、修改业务,JDBC的URL中去掉schema,把后面用户表都显式带上schema;3、运行业务;4、停止业务,重新调起重分布。source /opt/huawei/Bigdata/mppdb/.mppdbgs_profilegs_expand -t redistribute --fast-redis --parallel-jobs=12 --redis-mode=read-only方案二:1、停止重分布进程;1)omm用户登录第一个cn节点;2)找到gs_redis进程并将其kill -9 杀掉ps -ef |grep gs_redis|grep -v grep找到重分布进程pidkill -9 pid 杀掉重分布进程ps -ef |grep gs_redis|grep -v grep确认进程已被kill掉3)连接第一个cn,将数据重分布活跃语句全部终止掉SELECT pg_terminate_backend(pid);2、修改所有cn上老nodegroup的in_redistribution=n;并kill cn进程alter table pgxc_group set in_redistribution='n' where group_name=old_group;kill cn进程ps -ef |grep coordinator|grep -v grep|awk -F ' ' '{print $2}'|xargs kill -93、运行业务,需要保证业务中无跟表相关的ddl,跟表关联的对象的ddl,函数返回值带表类型的ddl等操作,否则会造成新老节点元数据不一致;4、停止业务,修改所有cn上老nodegroup的redistribute=y;并kill cn进程alter table pgxc_group set in_redistribution='y' where group_name=old_group;kill cn进程ps -ef |grep coordinator|grep -v grep|awk -F ' ' '{print $2}'|xargs kill -95、重新调起重分布。source /opt/huawei/Bigdata/mppdb/.mppdbgs_profilegs_expand -t redistribute --fast-redis --parallel-jobs=12 --redis-mode=read-only
  • [其他] 【故障】【内存】内存不可用报错:memory temporarily unavailable 的排查方法
    1.当出现memory temporarily unavailable报错时,首先根据报错信息确认具体是哪个cn/dn报的,如果报错信息前面没有类型dnxxxx_xxxx这样的信息,就是cn报的,需要去每个cn的日志里排查是哪个cn2.通过free -g或top查看当前内存的使用情况,确认是操作系统内存耗尽,还是因为cn/dn的内存使用达到限制,如果已经没有现场,可以通过查看/var/log/osinfo中的meminfo来确认当时操作系统的可用内存;meminfo日志:下面我们分两种场景讨论场景一:操作系统没有可用内存对于操作系统内存耗尽的场景,往往会触发操作系统的oom保护机制,这个在/var/log/message中可以搜索关键字‘kill’可以找到相关信息;操作系统在oom杀掉进程时,会打印各个进程的内存使用情况,需要注意的是,rss列的单位并不是b,而是page,在x86服务器上需要乘以4k来计算得到进程实际使用内存大小,在arm服务器上要乘以16k通过比较进程被杀时的内存和max_process_memory,如果被杀时仍未达到max_process_memory,则需考虑max_process_memory是否设置过大,可调整参数解决如果进程被杀时内存已经超过了max_process_memory,可使用下面两个语句进一步分析常用的监控语句1)查看各类内存使用情况select * from pv_total_memory_detail;2)查看占用dynamic内存最高的语句select * from (selectsessid,sum_total,sum_free,sum_used,query_id,query_start,state,waiting,enqueue,queryfrom(selectsessid,sum(totalsize) as sum_total,sum(freesize) as sum_free,sum(usedsize) as sum_usedfrompv_session_memory_detailgroup bysessid ) a,pg_stat_activity bwheresplit_part ( a.sessid,'.' , 2 ) = b.pid )order bysum_total desclimit 10;注:上述第二条监控语句只是排查dynamic内存高的场景,如果第一条语句查出来的结果不是dynamic_used_memory或dynamic_peak_memory高,而是其他内存(other_used_memory、sctpcomm_used_memory等),则需另做排查,以后再开帖子详细介绍场景二:操作系统仍有可用内存,cn/dn实例的dynamic内存使用达到上限对于有现场的情况,可以使用上面的第二条sql语句找到占用内存最高的语句,杀掉该语句并进行整改对于没有现场的情况,可以部署监控脚本等待下次复现另外,如果实例是cn,往往是因为有大量的不下推语句,可以在日志中搜索can't be shipped查看不下推的语句,并进行整改
  • [其他] 【总结】一分钟定位等锁问题
    我们经常遇见等锁问题,通过视图查询非常繁琐,我们可以通过如下方式快速准确找到持锁的语句:set lockwait_timeout=1000;    --表锁等待超时时间,默认20min,danwei msset update_lockwait_timeout=1000;  --行锁等待超时时间,默认2minset max_query_retry_times=0;  -- cn_retry 次数,默认为6次设置完成后,执行等锁的语句。很快就会报错,根据报错信息可以快速找到持锁线程和语句。例如:会话一会话二start transaction; drop table aa;set lockwait_timeout=1000;set update_lockwait_timeout=1000;set max_query_retry_times=0;select * from aa;此时会话二会很快报错,通过报错信息很快就能找到持锁语句和线程:ERROR:  Lock wait timeout: thread 140354461361920 on node coordinator1 waiting for AccessShareLock on relation 16655 of database 14764 after 2000.057 msLINE 1: select * from aa;                      ^DETAIL:  blocked by hold lock thread 140354804238080, statement <drop table aa;>, hold lockmode AccessExclusiveLock.找到持锁线程并从业务侧确认可以杀掉该线程后,可以登录对应的实例(上面报错是coordinator1,实际可能是其他实例),使用如下语句杀掉该线程:select pg_terminate_backend(140354804238080);也可以通过在CN上执行以下语句杀掉excute direct on(xxxx) select pg_terminate_backend(140354804238080);  (xxxx为报错的实例名称)杀掉后,可以通过下面语句确认是否已经杀掉:select * from pgxc_stat_activity where pid='140354804238080';确认杀掉后,重新执行语句即可。
  • [技术干货] 2020-10-20:线程池如何保证核心线程不被销毁?
    2020-10-20:线程池如何保证核心线程不被销毁?#福大大架构师每日一题#
  • [其他] 【重分布】数据重分布重入时delete pgxc_redistb操作耗时长,3小时以上无法完成
    发生版本【GaussDB A】【C80SPC600】问题描述将重分布进程杀掉重入,长时间不能进入表重分布阶段,后台查看第一个cn上PG_STAT_ACTIVITY视图,发现是在执行如下语句:delete from pgxc_redistb where(nspname, relname) not in ( select n.nspname, c.relname from pg_class c,pg_namespace n where c.relnamespace = n.nspname);问题分析重分布重入时需要先将pgxc_redistb中已完成重分布的表记录剔除掉,此剔除语句执行慢。解决方案1、首先停止重分布进程;2、查看当前事务,cancel掉redis进程调起的语句   select pg_cancel_backend(pid)  from pg_stat_activity where application_name = 'gs_redis' and query like 'DELETE FROM pgxc_redistb%';3、修复表字段,在每个数据库下执行语句:set enable_cluster_resize = on;alter table pgxc_redistb alter column relname set not null;alter table pgxc_redistb alter column nspname set not null;4、重新调起重分布命令。
  • [其他] 【总结】【GDS】GDS常见问题FAQ
    GDS常见问题FAQ【转载】原文链接:cid:link_0Q1:集群遇见报错unexpected EOF on GDS怎么处理?原因分析:当集群中出现大量这种错误时候首先考虑GDS机器的网络参数设置是否符合要求。可以参考下面的参数参数参考值:net.core.somaxconn = 65535 net.ipv4.tcp_max_syn_backlog = 65535 net.core.netdev_max_backlog = 65535 net.ipv4.tcp_retries1 =5 net.ipv4.tcp_retries2 = 60 查看方法cat /proc/sys/net/core/somaxconn cat /proc/sys/net/ipv4/tcp_max_syn_backlog cat /proc/sys/net/core/netdev_max_backlog cat /proc/sys/net/ipv4/tcp_retries1 cat /proc/sys/net/ipv4/tcp_retries2修改方法修改对应参数: vim /etc/sysctl.conf 永久生效: sysctl -pQ2: GDS遇到到网络层错误 “connection timed out” 怎么处理?原因1:由于高并发导入导出时GDS端向DN造成发送数据网络拥塞,当出现发送不成功后GDS会接收到网络层错误connection timed out 并主动 断开连接,之后DN 在下次请求GDS数据时也会接收到connection reset by peer 网络层错误. 经常发生在 数据传输过程中,可以调整系统 net.ipv4.tcp_retries2和 net.ipv4.tcp_retries1 参数原因2: 也可能是因为gds处理请求较慢,以至于backlog listen队列被填满后,新来的请求会被拒绝,一般发生在建连截断。可以调大net.core.somaxconn参数解决解决方法: 同上:net.core.somaxconn = 65535 net.ipv4.tcp_max_syn_backlog =65535 net.core.netdev_max_backlog = 65535 net.ipv4.tcp_retries1 = 5 net.ipv4.tcp_retries2 = 60 原因3: 大集群上arp路由表缓存溢出导致业务报错:connection reset by peer: gc_thresh1,gc_thresh2,gc_thresh3参数是默认值128 512 1024,DN分布在多个服务器机器上,导致连接过来接近512的arp缓存淘汰上限,可能会触发连接不识别被关闭等问题 解决方法:gc_thresh1 = 512 gc_thresh2 = 2048 gc_thresh3 = 4096Q3: DN 报错 ”The peer GDS has performed an orderly shutdown on current connection.“ 什么原因?可能原因:gds挂掉tcp连接异常,参考上面两种情况修改gds参数。gs_check巡检集群系统参数是否合理.Q4: GDS报错句柄不足,报错 too many open file 怎么处理?原因分析: gds进程占用的文件句柄超过设置的值。 解决办法:修改最大进程打开文件句柄数:/etc/security/limits.conf* soft nofile 640000 * hard nofile 640000 修改/etc/security/limits.d/*目录里的配置文件,对于配置文件中存在nofile配置的都需要修改,没有就跳过; 默认优先使用limits.d目录里的配置,再使用limits.conf的配置* soft nofile 640000 * hard nofile 640000修改 /etc/systemd/system.conf,修改行:DefaultLimitNOFILE=640000 保存退出.重新加载systemd服务配置systemctl daemon-reload systemctl daemon-reexec重新打开一个session 以集群用户重启gds进程.执行cat /proc/gds的pid/limits查询,参数已更改.Q5: GDS导入发现集群gaussdb IO异常高100%什么原因?可能原因: 内表中包含了大量索引,如果是btree索引导数过程中大量的索引操作导致系统IO非常高。 排查方法: iotop 观察哪一个进程占用的io非常高, Total DISK READ: 0.00 B/s | Total DISK WRITE: 259.32 K/s TID PRIO USER DISK READ DISK WRITE SWAPIN IO&gt; COMMAND 111958 be/4 sheng 0.00 B/s 16.73 K/s 0.00 % 0.00 % postgres: stats collector 54920 be/4 sheng 0.00 B/s 6.69 K/s 0.00 % 0.00 % gaussdb --coordinator -i -p 44548 -c log_statement=all -M normal -c logg~ sheng/GAUSS200_OLAP_TRUNK/Code/src/test/regress/./tmp_check/coordinator2 54986 be/4 sheng 0.00 B/s 500M/s 0.00 % 0.00 % gaussdb --datanode -i -p 44556 -c log_statement=all -M normal -c 发现 dn 进程号54986 写io非常高。gstack 54986|grep -i write查看当前进程在做什么操作Q6: ERROR: dn_6001_6002: GDS max line size 1073741823 is exceeded. 为什么?原因分析: GDS导数时候为了避免文件格式异常导致识别的单行数据过大甚至导致系统oom的场景,gds端限制单行不能超过1G。 解决方法: 首先考虑是否因为csv文件的quote没有成对出现,如果确实是因为quote导致的可以考虑修改外表的quote为不可见字符;其次考虑单行数据是否确实的超过1G,手动删除改行。Q7: Cannot enlarge buffer containing 1078343432 bytes by 40783434 为什么?原因分析:copy或者导入的时候可能由于csv文件格式于文件格式异常导致识别的单行数据过大超过1G;或者单行数据大于1G。解决方法: 出现此错误时候首先考虑是否因为csv文件的quote没有成对出现,可以考虑修改sql的quote为不可见字符; 其次考虑单行数据是否确实的超过1G,手动删除改行。Q8: "unexpected message type 0x58 during COPY from stdin" 为什么原因分析: 由于进群故障,如dn宕机后并且不能重试,cn会向dn下发‘X' 报文意味着cn正在关闭socket。属于正常报错信息。 解决办法: 查看集群日志分析为什么集群出现故障。Q9: 为什么乱码?原因分析:乱码的原因本质上是因为 字符编码转换不匹配copy或者gds导入文件中存在混合编码 或者不能转换的字符 存在的原因: 文件来源于另外一个数据库系统,比如oracle或者gaussdb数据库编码设置为"不校验编码"一般为标准ascii类编码比如postgresql中的sqlascii编码,mysql中使用latin1作为"不校验编码"。 由于这种编码数据库内部都不做校验因此用户无论给定什么编码的数据他都会以字节流的方式存起来(也叫错入错处)但是这样会导致一张表里包含不同的编码的数据,如果从这样的系统导出文件自然文件中也会包含不同编码的内容。当使用这种文件导入到gaussdb中的时候有可能报错如“invalid byte sequence for encoding 'utf8': 0xc3”表示0xc4不是一个有效的utf8编码,或者会将乱码字符插入数据库。 预防方法: 设置客户端,外表,数据库的编码一致 。解决方法: 设置gds或者copy的容错参数,或者使用iconv 命令将文件转码为统一的编码(其实iconv遇到转换不了的也会报错或者替换成?之类的字符和gaussdb的容错思路差不多) gds或者copy 的容错机制中有一种可以规避(注意是规避)这个问题。 gds和copy都有一个参数"COMPATIBLE_ILLEGAL_CHARS" 会将转换不了的字符替换成‘?'Q10: 怎么确定文件编码和文件内容是什么编码?其实一般程序更关心文件内容是什么编码而不是文件是什么编码,文件是什么编码取决于bom头写的是什么编码,文件是什么编码取决于结出来的编码有无乱码。 **注意:通过file 命令或者使用vim看到的编码格式不一定是实际的编码,因为他们都是通过识别bom头来确定是什么编码的,但是有些程序写入的数据并不会像在window上那样设置编码格式头也叫“bom头"**。教一个方法:将你设置了终端(xshell后者crt)编辑器显示的编码打开文件如果发现语句通顺那这个文件中的内容就是你终端和编辑器的编码。 在中国大陆能看到最多的编码转换问题大多数是由于gbk,gb2312和utf8 的转换问题或者latin1和utf8的编码转换问题。如果不是这两种问题最好能转换成这种问题。因为gaussdb和pg数据库最擅长的就是处理这些编码转换。​编码建议:目前线网最常见的编码转换仍然是gbk到utf8编码的转换。虽然gaussdb数据库服务端已经支持设置GBK字符集但是强烈建议在设计之初将服务端数据库编码设置成utf8编码,因为utf8可以识别gbk识别不了的字符,除非你的系统以后都只服务汉字人群。 也不建议将数据库编码设置为“sqlascii”,虽然很灵活但是非常率容易出现混合编码后期维护很差。如果后面要插入一些比较特殊的字符,虽然目前gaussdb已经支持了服务端的GBK编码但是某些场景可能尚未考虑到。sqlascii编码虽然方便但是后期不好维护。比如gaussdb目前latin1和gbk是不能互相转换的,但是latin1和utf8就可以互相转换。Q11: GDS外表无数据查询为什么hang?解决方法:查询gds和集群是否网络畅通.查询外表定义中location网络地址是否畅通。查询外表定义中location的协议是否正确对应 ssl->gsfss 普通协议->gsfs集群gtm或者dn故障。Q12: GDS外表有数据数据查询为什么hang?。解决方法:查询gds和集群是否网络畅通.查询外表定义中location网络地址是否畅通。查询外表定义中location的协议是否正确对应 ssl->gsfss 普通协议->gsfs集群gtm或者dn故障。网络拥塞:排查gds发送端 网络拥塞情况 netstat -taucp|grep gds端口 tcp 0 74457 mpp116:31001 mpp098:62506 ESTABLISHED 48541/gds排查DN接受端 网络拥塞情况 netstat -taucp|grep gds端口 cp 0 0 mpp098:62506 mpp116:31001 ESTABLISHED 8824/gaussdb观察现象发现GDS端TCP的Send Queue中堆积了大量数据,而DN端Recv Queue中无任何数据。并且通过-t的实时打印可以发现GDS端TCP的Send Queue中数据在一个较长的时间段能不会减少,而且数据减少的周期非常长且亦有阶段性,而DN端未检测到Recv Queue中有数据。因此定位为TCP连接数据传输被阻塞。Q13: GDS -t 参数原理是什么?设置GDS并发线程数,其实是设置了GDS指的工作线程池大小。比如-t 指定为10 系统回见测试当前是否有空工作线程且当前工作线程小于10时候才会创建新线程,不会一启动就事先创建10个线程。GDS是根据导入事务并发数来决定服务运行线程数的。也就是说即使启动GDS时设置了多线程,也并不会加速单个导入事务。未做过人为事务处理时,一条INSERT语句就是一个导入事务.
  • [技术干货] 【转载】Python 并发编程之进程理论知识 -&gt; 进程的并行与并发
    理论知识之进程的并行与并发并行 : 并行是指两者同时执行,比如赛跑,两个人都在不停的往前跑;(资源够用,比如三个线程,四核的CPU )并发 : 并发是指资源有限的情况下,两者交替轮流使用资源,比如一段路(单核CPU资源)同时只能过一个人,A走一段后,让给B,B用完继续给A ,交替使用,目的是提高效率。区别:并行是从微观上,也就是在一个精确的时间片刻,有不同的程序在执行,这就要求必须有多个处理器。并发是从宏观上,在一个时间段上可以看出是同时执行的,比如一个服务器同时处理多个session。
  • [技术干货] 2020-10-07:redis存在线程安全的问题吗?为什么?
    2020-10-07:redis存在线程安全的问题吗?为什么?#福大大架构师每日一题#
  • [技术干货] 2020-10-06:java中垃圾回收器让工作线程停顿下来是怎么做的?
    2020-10-06:java中垃圾回收器让工作线程停顿下来是怎么做的?#福大大架构师每日一题#
  • [Java] synchronized关键字
    synchronized也叫同步锁,是Java里面的关键字。我们可以猜测到synchronized原理也JVM虚拟机有关联。synchronized锁的是对象。对象里面有一个叫做监视锁(monitor)的东西,监视锁依赖操作系统的互斥锁(Mutex Lock)。操作系统切换线程其实就是从用户态编程核心态(cpu的两种状态)。这个代价有点高,所以synchronized这个重量级锁后面也引进了偏向锁和轻量级锁。加锁(监视锁monitor)过程分析():当monitor的进入数为0,线程A进入monitor的进入数为1线程B想进入该monitor就会被阻塞。线程A可以重复进入该monitor,所以synchronized是可重入锁,和Lock实现的锁一样。程序验证public class SynchronizedTest {    private static  int i = 0;    public static void main(String[] args) {    test();   }   public static void test(){    synchronized (SynchronizedTest.class){        synchronized (SynchronizedTest.class){            i++;            }        }    }}运行结果程序正常运行,没有报错synchronized可以修饰方法以及代码块,代码块就是上面重入锁的例子。修饰方法public class SynchronizedTest {    static int n = 100;    final static CountDownLatch start = new CountDownLatch(n);    private static  int i = 0;    public static void main(String[] args) throws InterruptedException {        for (int j = 0; j < n; j++) {            Thread thread = new Thread(new addNoSynchronized());            thread.start();        }        start.await();        System.out.println(i);    }    public static class addSynchronized implements Runnable{        @Override        public void run() {            addSynchronized();        }        public static synchronized void addSynchronized(){            for (int j = 0; j < 1000; j++) {                i++;            }            start.countDown();        }    }}运行结果Copy100000如果去掉 synchronized 关键字的话,运行结果大概率不是 100000,因为线程不安全问题。
总条数:813 到第 页
上滑加载中