使用SequoiaDB驱动多线程开发常见错误分析

来源:互联网 发布:手机播音软件 编辑:程序博客网 时间:2024/04/29 15:30

一、摘要

工作上的需要,最近使用国内的一款NoSQL数据库SequoiaDB。由于对SequoiaDB不太了解,刚开始在驱动的使用上踩了不少坑,这里做一个简单的分享。SequoiaDB在多线程应用中,需要确保一个连接对象(以及由其衍生出来的所有集合或其它对象)不会同时被多个线程所访问。大家在使用驱动进行多线程开发时,如果使用不当,有可能会遇到各种各样的问题。本文将给大家讲述在使用SequoiaDB驱动进行多线程开发时,应该注意的问题。

二、现象描述

下面是使用使用不当,而可能导致的一些结果:

  • 客户端收到-65(Unexpected result received)错误。
  • 客户端卡死
  • 客户端得到不正确的结果
  • 客户端崩溃

为了分析以上几种错误,我们需要了解SequoiaDB驱动在实现上的一些细节。
目前(1.12)SequoiaDB驱动一般会有以下几种类(以本人使用Java驱动为例,其它驱动也一样):

  • Sequoiadb
  • CollectionSpace
  • DBCollection
  • DBCursor
  • DBLob
  • DBDomain
  • ReplicaGroup
  • ReplicaNode

这些类在实现上,有以下两个特点:
1. 所有对象共用Sequoiadb对象的socket,如下面代码所示:

Sequoiadb db       = null;CollectionSpace cs = null;DBCollection cl    = null;DBCursor cursor    = null;DBLob lob          = null;...db = new Sequoiadb("192.168.20.42", 11810, "", ""); // 建立连接cs = db.createCollectionSpace("foo");cl = cs.createCollection("bar");cursor = cl.query();lob = cl.createLob();...

建立连接后,db对象将持有一个socket对象,当db对象创建cs对象,cs对象创建cl对象,cl对象创建cursor,lob对象后,所有对象都共用db所持有的socket对象。如果将这些对象分配到不同的线程中去使用,将会面临一个socket对象在多个线程中使用的问题。目前,SequoiaDB驱动并没有对这个共用的socket对象加锁保护。所以,将这些共用同一个socket的对象放到不同的线程去使用是不安全的。
2. 每个对象都有自己的send buffer/receive buffer
上述的每个对象,都有各自的独立的send buffer/receive buffer。这些buffer在使用的时候也是没有加锁保护的。如果将一个对象,放在多个线程中去使用,有可能出现对象发送或接收的内容被修改的情况。

SequoiaDB所有驱动都没有加锁保护。由于存在以上两点,大家在使用多线程开发时,需要合理使用这些对象。

三、问题分析

对上面列出的几种错误情况,下面讲述它们出错的原因。

1. 客户端收到-65(Unexpected result received)错误。
当多线程使用不当时,客户端最容易收到-65(Unexpected result received)错误。SequoiaDB驱动每次和数据库交互时,都会校验它发送和接收的消息。如果驱动发送的是一个query的请求,但却收到一个update请求的应答,那么驱动将报出一个-65的错误。造成这种收错消息的原因基本上就像上面所说的:1、共用一个socket的两个对象放在不同的线程中使用,造成彼此收错消息的情况。2、同一个对象(假设为cl对象),放在了不同的线程中使用,cl在A线程中把query请求的应答收回到receive buffer中,准备提取query的结果时,cl在B线程中update请求的应答刚好也收回到receive buffer中,并把query请求的内容覆盖掉,这时,cl在A线程中便出现收错消息的情况。

2. 客户端卡死
这种情况发生在客户端发送一个请求给数据库,而数据库没有发应答数据包给客户端的时候。在Sequoiadb驱动与数据库交互的命令中,有几个命令数据库是不需要回复应答给驱动的,disconnect就是其中一个。考虑以下场景:db对象被放到A、B两个线程。在A线程中,db发了一个create collection space的消息给数据库,数据库收到这个请求,需要回复一个应答给驱动。但是,在A线程中,db对象准备发送消息的前一刻,send buffer中的内容被B线程中的db对象修改了,改为了发送一个disconnect的消息。这样,数据库只收到一个disconnect的消息,它不会给A线程的db对象回应答包,于是,A线程就出现死等的情况。

3. 客户端得到不正确的结果
这个情况和收到-65错误的情况很相似。假设在A、B两个线程中,共用同一个socket的两个cl对象都向数据库发送不同条件的query请求,而结果它们又彼此收错了对方的应答消息包,那么业务层必然得到错误的结果。

4. 客户端崩溃
对象的send buffer/receive buffer的大小根据不同消息命令可以设置不同的大小,如果将一个对象放在不同线程去使用,有可能出现A线程在使用buffer的时候,buffer刚好被B线程删除掉,重新建。这时,A线程就极有可能因为访问非法内存而导致整个客户端崩溃。另外一种可能是,A线程在发送或接收前一刻,socket资源被B线程释放了,那么,A线程也面临着访问非法内存而导致客户端崩溃的问题。

四、建议

以上分析了几种在多线程中不恰当使用对象而导致错误的情况。目前,SequoiaDB驱动对于多线程并发的场景还有很大可以提升的空间。如果大家需要使用多线程开发,应当避免:

  • 将共用同一个socket的几个对象放到不同的线程使用。
  • 将一个对象放到不同的线程中使用。

大家可以如下使用SequoiaDB驱动在多线程中开发:

  • 共用同一socket的对象只能被同一线程持有
  • 确保共用同一socket的所有对象都释放后,再释放db对象(Sequoiadb对象)
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 拉链从下面开了怎么办 高帮足球鞋松了怎么办 橡筋裤头太紧了怎么办 内增高鞋跟太高怎么办 电脑增高架高了怎么办 银行取钱走后回来说少了怎么办 运动t桖太大了怎么办 袖口松紧太紧了怎么办 衣服穿着就皱了怎么办 麻料的衣服很皱怎么办 麻料衣服皱了怎么办 棉麻裤子皱了怎么办 裙子屁股坐皱了怎么办 真丝衣服洗皱了怎么办 粘纤的衣服皱了怎么办 硅胶手机壳粘灰怎么办 橡筋裤子买大了怎么办 橡筋裤子腰小了怎么办 地垫粘瓷砖上怎么办 汽车围裙锈透了怎么办 万能胶水沾到手上怎么办 圆领体恤领口容易皱怎么办 上衣剪了个洞怎么办 上衣破了个洞怎么办 鸟屎腐蚀车漆怎么办 毛风衣叠久了怎么办 黑色的衣服沾毛怎么办 雪纺裙子弄上油怎么办 内衣买小了怎么办妙招 长裤衬衫裙邹了怎么办 100棉衬衣皱了怎么办? 短袖t恤袖口大了怎么办 短袖底下卷边了怎么办 棉质短袖衫缩水怎么办 纯棉t恤缩水了怎么办 t恤缩水变小了怎么办 衣服掉在雨棚上怎么办 车衣密码锁忘记密码怎么办 衣服的铁拉链弯怎么办 去旅行衣服皱了怎么办 衣服抽绳出来了怎么办