处理并发问题的最佳方式 [英] Best way to handle concurrency issues

查看:136
本文介绍了处理并发问题的最佳方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个LAPP(linux,apache,postgresql和php)环境,但问题是在Postgres或Mysql是相同的。



我有一个cms应用程序开发,处理客户端,文档(估计,发票等)和其他数据,结构在1 postgres DB与许多模式(每个我们的客户使用应用程序);让我们假设大约200个模式,每个模式由15个人(avg)并发使用。



EDIT :我有一个名为last_update



情况是:



ol>
  • People Foo和Bar正在使用包含每个文档详细信息的表单编辑文档0001。

  • 例如,更改装运详细信息。

  • 更改电话号码和文档中的某些项目。

  • Foo按保存按钮,应用程序更新数据库。
  • 在栏后按保存按钮,重新发送包含旧装运详细信息的表单。

  • 在数据库中,Foo更改已丢失。 li>

    我想要的情况:



    1. 例如,更改装运详细信息。

    2. Bar和其他人改变了别的东西。

    3. Foo按下保存按钮,应用程序更新数据库。

    4. 而其他人得到警报警告!此文档已由其他人更改。

    我想要使用ajax来执行此操作。只需使用具有文档的id和最后更新的时间戳的隐藏字段,每5秒检查最后更新的时间是否相同并且什么都不做,否则显示警告对话框。



    因此,页面check-last-update.php应该类似于:

      ?php 
    // [连接到db,postgres或mysql]
    $ documentId = isset($ _ POST ['document-id'])? $ _POST ['document-id']:0;
    $ lastUpdateTime = isset($ _ POST ['last-update-time'])? $ _POST ['last-update-time']:0;
    //在现实生活中我清理数据和使用准备语句;
    $ qr = pg_query(
    SELECT
    last_update_time
    FROM
    文档
    WHERE
    id ='$ documentId'
    );
    $ ray = pg_fetch_assoc($ qr);
    if($ ray ['last_update_time']> $ lastUpdateTime){
    //自我打开文档后,其他人更新了文档!
    echo'reload';
    } else {
    echo'ok';
    }
    ?>

    但我不喜欢每5秒强调一个数据库。

    p>

    我想使用文件,为每个文档创建一个空的txt文件,并且每次文档更新,我'触摸'更新'上次修改时间'但是我想,这将比数据库慢,并给我的问题,当我有很多用户编辑同一个文档。



    如果有人有一个更好的想法或任何建议,请详细描述!



    * - - - - - UPDATE - - - - - * b
    $ b

    我明确选择不敲db检查'最后更新时间戳',不介意如果查询会很快,(主)数据库服务器有其他任务完全填充,不



    所以,im采取这种方式:


    1. 每次有人更新文档时,我必须在db环境外签名新的时间戳,例如而不需要db。我的想法是:


      1. 文件系统:对于每个文档,我创建一个empry txt文件命名为文档的id,文档更新,我'触摸'文件。我希望有数千个空文件。

      2. APC,php缓存:这将是一个比第一个更灵活的方式,但我想知道是否保持成千上万的数据永久在apc不会减慢php执行本身,或者消耗服务器内存。

      3. 另一个db,sqlite或mysql(使用简单的数据库结构更快更轻)用于仅存储文档ID和时间戳。


    2. 无论我选择什么方式(文件,apc,sub-db)
    3. 还有其他编辑

      >

      文件的方式无效。



      APC可以是解决方案。



      击中数据库也可以是解决方案,创建一个表来处理时间戳(只有两列,document_id和last_update_timestamp)需要尽可能快和轻。



      长轮询:这是我选择的方式,使用lighttpd在apache下加载静态文件(图像,CSS,JS等),只是这种类型的长轮询;这将减轻apache2的负载,特别是用于轮询。



      Apache会将所有这些请求代理到lighttpd。



      现在,我只需要决定db解决方案和APC解决方案。



      ps:感谢所有已经回答我,你一直真的有用! / p>

      解决方案

      我同意我可能不会打这个数据库。我想我会使用APC缓存(或一些其他内存缓存)来维护这些信息。你所描述的是明确乐观的锁定在详细的记录水平。数据库结构中的级别越高,您需要处理的就越少。这听起来像你想检查一个结构中的多个表。



      我将维护一个高速缓存(APC)的ID和最后更新时间的时间戳keyed由表名。因此,例如,我可能有一个表名称数组,其中每个条目由ID键入,实际值是最后更新的时间戳。可能有很多方法来设置它与数组或其他结构,但你得到的想法。我可能会添加一个超时缓存,使缓存中的条目在一段时间后被删除 - 即,我不想要缓存增长,并假设1天的条目不再有用了。)



      使用此架构,您需要执行以下操作(除了设置APC):




      • 在任何(适用的)表的任何更新上,使用新的时间戳记更新APC缓存条目。

      • 作为远回为php(以获得APC缓存来检查条目)而不是所有的回到数据库。



      i have a LAPP (linux, apache, postgresql and php) environment, but the question is pretty the same both on Postgres or Mysql.

      I have an cms app i developed, that handle clients, documents (estimates, invoices, etc..) and other data, structured in 1 postgres DB with many schemas (one for each our customer using the app); let's assume around 200 schemas, each of them used concurrently by 15 people (avg).

      EDIT: I do have an timestamp field named last_update on every table, and a trigger that update the timestamp every time the row is update.

      The situation is:

      1. People Foo and Bar are editing the document 0001, using a form with every document details.
      2. Foo change the shipment details, for example.
      3. Bar change the phone numbers, and some items in the document.
      4. Foo press the 'Save' button, the app update the db.
      5. Bar press the 'Save' button after bar, resending the form with the old shipment details.
      6. In the database, the Foo changes have been lost.

      The situation i want to have:

      1. People Foo, Bar, John, Mary, Paoul are editing the document 0001, using a form with every document details.
      2. Foo change the shipment details, for example.
      3. Bar and the others change something else.
      4. Foo press the 'Save' button, the app update the db.
      5. Bar and the others get an alert 'Warning! this document has been changet by someone else. Click here to load the actuals data'.

      I've wondered to use ajax to do this; simply using an hidden field with the id of the document and the last-updated timestamp, every 5 seconds check if the last-updated time is the same and do nothing, else, show the alert dialog box.

      So, the page check-last-update.php should look something like:

      <?php
      //[connect to db, postgres or mysql]
      $documentId = isset($_POST['document-id']) ? $_POST['document-id'] : 0;
      $lastUpdateTime = isset($_POST['last-update-time']) ? $_POST['last-update-time'] : 0;
      //in the real life i sanitize the data and use prepared statements;
      $qr = pg_query("
          SELECT
              last_update_time
          FROM
              documents
          WHERE
              id = '$documentId'
      ");
      $ray = pg_fetch_assoc($qr);
      if($ray['last_update_time'] > $lastUpdateTime){
          //someone else updated the document since i opened it!
          echo 'reload';
      }else{
          echo 'ok';
      }
      ?>
      

      But i dont like to stress the db every 5 seconds for every user that have one (or more...) documents opened.

      So, what can be another efficent solution without nuking the db?

      I thought to use files, creating for example an empty txt file for each document, and everytime the document is updated, i 'touch' the file updating the 'last modified time' as well... but i guess that this would be slower than db and give problems when i have much users editing the same document.

      If someone else have a better idea or any suggestion, please describe it in details!

      * - - - - - UPDATE - - - - - *

      I definitely choosen to NOT hit the db for check the 'last update timestamp', dont mind if the query will be pretty fast, the (main) database server has other tasks to fullfill, dont like the idea to increase his overload for that thing.

      So, im taking this way:

      1. Every time a document is updated by someone, i must do something to sign the new timestamp outside the db environment, e.g. without asking the db. My ideas are:

        1. File-system: for each document i create an empry txt files named as the id of the document, everytime the document is update, i 'touch' the file. Im expecting to have thousands of those empty files.
        2. APC, php cache: this will be probably a more flexible way than the first one, but im wondering if keeping thousands and thousands of data permanently in the apc wont slow down the php execution itself, or consume the server memory. Im little bit afraid to choose this way.
        3. Another db, sqlite or mysql (that are faster and lighter with simple db structures) used to store just the documents ID and timestamps.

      2. Whatever way i choose (files, apc, sub-db) im seriously thinking to use another web-server (lighttp?) on a sub-domain, to handle all those.. long-polling requests.

      YET ANOTHER EDIT:

      The file's way wouldnt work.

      APC can be the solution.

      Hitting the DB can be the solution too, creating a table just to handle the timestamps (with only two column, document_id and last_update_timestamp) that need to be as fast and light as possible.

      Long polling: that's the way i'll choose, using lighttpd under apache to load static files (images, css, js, etc..), and just for this type of long-polling; This will lighten the apache2 load, specially for the polling.

      Apache will proxy-up all those request to lighttpd.

      Now, i only have to decide between db solution and APC solution..

      p.s: thanks to all whom already answered me, you have been really usefull!

      解决方案

      I agree that I probably wouldn't hit the database for this. I suppose I would use APC cache (or some other in-memory cache) to maintain this information. What you are describing is clearly optimistic locking at the detailed record level. The higher the level in the database structure the less you need to deal with. It sounds like you want to check with multiple tables within a structure.

      I would maintain a cache (in APC) of the IDs and the timestamps of the last updated time keyed by the table name. So for example I might have an array of table names where each entry is keyed by ID and the actual value is the last updated timestamp. There are probably many ways to set this up with arrays or other structures but you get the idea. I would probably add a timeout to the cache so that entries in the cache are removed after a certain period of time - i.e., I wouldn't want the cache to grow and assume that 1 day old entries aren't useful anymore).

      With this architecture you would need to do the following (in addition to setting up APC):

      • on any update to any (applicable) table, update the APC cache entry with the new timestamp.

      • within ajax just go as far "back" as php (to obtain the APC cache to check the entry) rather than all of the way "back" to the database.

      这篇关于处理并发问题的最佳方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆