ورود

View Full Version : درخواست راهنمایی در یک مسئله



reza_azizi2010
شنبه 20 اردیبهشت 1393, 09:41 صبح
سلام اساتید
من توی برنامه ام یه دیتابیس دارم، میخام این دیتابیس با دیتابیس کاربرهای دیگه سینک بشه.
نمیخام دیتابیس رو روی سایت بذارم، چون سرعت میاد پایین. دیتابیس باید لوکال روی گوشی باشه. تعداد کاربرها کمه و نهایتا 10 نفر. تغییرات هم نیازی نیست همون لحظه روی همه دیتابیسهای اعمال بشه. مثلا هروقت کاربر خودش خواست آپدیت بشه.
چه راهی پیشنهاد میکنید؟

rubiks.kde
شنبه 20 اردیبهشت 1393, 19:03 عصر
به هر حال شما نیاز داری یه چیزی در این وسط نقش سرور داشته باشه تا تمام دیتابیس ها در اون جا سینک بشن.

والا دو به دو که نمیشه همه رو سینک کرد.

اگه هم این طور نیست یکم بیشتر توضیح بده.

Nevercom
شنبه 20 اردیبهشت 1393, 20:55 عصر
درصورتی سرعت در دیتابیس ریموت کم هست که هربار بخواید اطلاعات رو از سرور بخونید و بعد نمایش بدید، شما بار اول اطلاعات رو بخونید و در دیتابیس لوکال ذخیره کنید، بصورت دوره ای اطلاعات رو در پس زمینه با سرور مرکزی سینک کنید.
همیشه برای نمایش اطلاعات رو از سرور لوکال بخونید که مشکل در سرعت نمایش اطلاعات نداشته باشید

همه ی کلاینت ها هم به همین روش با سرور سینک میشن

rubiks.kde
شنبه 20 اردیبهشت 1393, 21:29 عصر
درصورتی سرعت در دیتابیس ریموت کم هست که هربار بخواید اطلاعات رو از سرور بخونید و بعد نمایش بدید، شما بار اول اطلاعات رو بخونید و در دیتابیس لوکال ذخیره کنید، بصورت دوره ای اطلاعات رو در پس زمینه با سرور مرکزی سینک کنید.
همیشه برای نمایش اطلاعات رو از سرور لوکال بخونید که مشکل در سرعت نمایش اطلاعات نداشته باشید

همه ی کلاینت ها هم به همین روش با سرور سینک میشن

دوست عزیز سوال رو خوب خوندید؟

reza_azizi2010
شنبه 20 اردیبهشت 1393, 22:04 عصر
درسته حق با شماست آقا سعید، واسه بروزرسانی باید به یک سرور وصل بشه تا سینک کنه.
حالا موندم همینکارو چطور انجام بدم
مثلا یه کپی از دیتابیس رو سرور بذارم و اطلاعات کاربر رو مقایسه کنم و تغییرات رو اعمال کنم؟ خب اصلا چطوری مقایسه انجام بدم!

rubiks.kde
شنبه 20 اردیبهشت 1393, 22:19 عصر
درسته حق با شماست آقا سعید، واسه بروزرسانی باید به یک سرور وصل بشه تا سینک کنه.
حالا موندم همینکارو چطور انجام بدم
مثلا یه کپی از دیتابیس رو سرور بذارم و اطلاعات کاربر رو مقایسه کنم و تغییرات رو اعمال کنم؟ خب اصلا چطوری مقایسه انجام بدم!

دقیقا چطوریه؟همه دیتابیس ها باهم سینک بشن؟
یا هر کی جدا؟

اگه توی سرور بزاری تنها تغییرات توی گوشی هست و سرور نگه دارنده است؟

reza_azizi2010
شنبه 20 اردیبهشت 1393, 22:29 عصر
ببینید این یه برنامه است واسه یه فروشگاه که چندتا فروشنده داره. دیتابیس هم موجودی اجناس فروشگاهه (البته چیپس و پفک نمیفروشن ، اجناسشون محدوده و گرون!. زیر هزارتا جنس!)
هر فروشنده که یک جنس رو فروخت ، توی برنامه اش ذخیره میشه که اون جنس فروخته شده. حالا این اطلاعات باید واسه بقیه فروشنده ها هم بره که معلوم شه اون جنس فروخته شده.
البته خیلی حیاتی نیست که همون لحظه اصلاح بشه مثلا آخر شب که کاربر به اینترنت وصل شد میتونه اطلاعات خودش رو بفرسته به سرور و تغییرات بقیه کاربرا رو هم بگیره.
کاربرها فقط میتونن اطلاعات خودشون رو تغییر بدن، و دسترسی به سرور ندارن. و همونجور که شما گفتین ، سرور فقط تغییرات رو قراره نگه داره

reza_azizi2010
شنبه 20 اردیبهشت 1393, 22:32 عصر
یه سوال حاشیه ای هم دارم! من خیلی لوگ کت استفاده میکنم، و سعی میکنم همه جا رو مانیتور کنم. واسه خروجی گرفتن باید این لوگ کت هارو کامنت کنم؟ تو سرعت برنامه تاثیر داره؟

Nevercom
یک شنبه 21 اردیبهشت 1393, 00:40 صبح
دوست عزیز سوال رو خوب خوندید؟
تعبیر من از سوال ایشون این هست که نیازمند قابلیت سینک دیتابیس ها هستن، که همه ی کلاینت ها آخرین تغییرات رو داشته باشن.
اما به این دلیل نمیخوان دیتابیسی روی سرور داشته باشن و به فکر سینک نظیر به نظیر افتادن که احساس می کنن فرآیند ثبت تغییرات در دیتابیس مرکزی و خوندن داده ها از سرور مرکزی برای نمایش یا استفاده در برنامه بصورت مستقیم از سرور، کند هست.

پیشنهاد من هم این هست که همون سرور مرکزی رو داشته باشن چون راه حلی معقول برای قابلیت سینک هست، اما داده ها رو برای خودشون کش کنن تا برای نمایش نیاز به خوندن از سرور نباشه و تغییرات رو هم در دیتابیس لوکال ذخیره کنن و اگر اینترنت موجود هست در بکگراند اطلاعات رو به سرور بفرستند یا اطلاعات جدید رو دریافت کنن که وقفه ای در عملکرد برنامه ایجاد نکنه.

شاید من سوال رو اشتباه متوجه شدم.

reza_azizi2010
یک شنبه 21 اردیبهشت 1393, 12:40 عصر
تعبیر من از سوال ایشون این هست که نیازمند قابلیت سینک دیتابیس ها هستن، که همه ی کلاینت ها آخرین تغییرات رو داشته باشن.
اما به این دلیل نمیخوان دیتابیسی روی سرور داشته باشن و به فکر سینک نظیر به نظیر افتادن که احساس می کنن فرآیند ثبت تغییرات در دیتابیس مرکزی و خوندن داده ها از سرور مرکزی برای نمایش یا استفاده در برنامه بصورت مستقیم از سرور، کند هست.

پیشنهاد من هم این هست که همون سرور مرکزی رو داشته باشن چون راه حلی معقول برای قابلیت سینک هست، اما داده ها رو برای خودشون کش کنن تا برای نمایش نیاز به خوندن از سرور نباشه و تغییرات رو هم در دیتابیس لوکال ذخیره کنن و اگر اینترنت موجود هست در بکگراند اطلاعات رو به سرور بفرستند یا اطلاعات جدید رو دریافت کنن که وقفه ای در عملکرد برنامه ایجاد نکنه.

شاید من سوال رو اشتباه متوجه شدم.
تقریبا همچین چیزیه، یعنی دیتابیسها روی تبلت کپی میشه و از روی تبلت هم بازیابی میشه. فقط میخام تغییرات بره روی سرور که بقیه هم اون تغییرات رو دریافت کنن.

daniel021
یک شنبه 21 اردیبهشت 1393, 12:41 عصر
تقریبا همچین چیزیه، یعنی دیتابیسها روی تبلت کپی میشه و از روی تبلت هم بازیابی میشه. فقط میخام تغییرات بره روی سرور که بقیه هم اون تغییرات رو دریافت کنن.

:متفکر::متعجب:

Nevercom
یک شنبه 21 اردیبهشت 1393, 13:17 عصر
روشی که من قبلاً برای یه پروژه ی آزمایشی استفاده کرده بودم به این شکل بود که با ورود به سیستم برای اولین بار، اطلاعات رو از سرور دریافت می کنه و در دیتابیس ذخیره می کنه (بروزترین اطلاعات هست)
هر تغییراتی که روی دیتابیس لوکال صورت بگیره در زمان مشخص برای سرور ارسال میشه و سرور چک می کنه و اطلاعاتی که لازمه رو آپدیت و جدیدها رو اضافه می کنه (حذف وجود نداره و فقط با تغییر وضعیتش نشون داده نمیشه)
برنامه های لوکال هم در زمان هایی که نیازه درخواستی رو به سرور ازسال می کنن که سرور بر اساس اون درخواست تشخیص میده آیا داده ی جدیتری موجود هست یا خیر.

فکر کنم از تگ زمانی استفاده کرده بودم، سعی می کنم پروژه رو پیدا کنم و کدها رو براتون بزارم

شما هم می تونید از روشی مشابه استفاده کنید

ضمن اینکه فکر می کنم دراپ باکس هم یک API برای قابلیت سینک داشت، اون رو هم بررسی کنید

reza_azizi2010
یک شنبه 21 اردیبهشت 1393, 17:11 عصر
روشی که من قبلاً برای یه پروژه ی آزمایشی استفاده کرده بودم به این شکل بود که با ورود به سیستم برای اولین بار، اطلاعات رو از سرور دریافت می کنه و در دیتابیس ذخیره می کنه (بروزترین اطلاعات هست)
هر تغییراتی که روی دیتابیس لوکال صورت بگیره در زمان مشخص برای سرور ارسال میشه و سرور چک می کنه و اطلاعاتی که لازمه رو آپدیت و جدیدها رو اضافه می کنه (حذف وجود نداره و فقط با تغییر وضعیتش نشون داده نمیشه)
برنامه های لوکال هم در زمان هایی که نیازه درخواستی رو به سرور ازسال می کنن که سرور بر اساس اون درخواست تشخیص میده آیا داده ی جدیتری موجود هست یا خیر.

فکر کنم از تگ زمانی استفاده کرده بودم، سعی می کنم پروژه رو پیدا کنم و کدها رو براتون بزارم

شما هم می تونید از روشی مشابه استفاده کنید

ضمن اینکه فکر می کنم دراپ باکس هم یک API برای قابلیت سینک داشت، اون رو هم بررسی کنید
خب من کلا الگوریتم سینک کردن رو میخام بدونم چطوریه
باید همه رکوردهارو یکی یکی چک کنم؟ یا مثلا یه فیلد تغییر بذارم که هر رکوردی که تغییر کرد اون فیلد مقدارش تغییر کنه
ممنون میشم در این مورد هم توضیح بدین

Nevercom
یک شنبه 21 اردیبهشت 1393, 18:38 عصر
راه حلی که من استفاده کرده بودم به این شکل بود:

آخرین تاریخ سینک رو از دیتابیس لوکال بخون (هر رکورد یه فیلد داره که تاریخ آخرین سینک رو نگه میداره)
تاریخ آخرین سینک رو به سرور بفرست
سرور چک می کنه اگه تاریخ آخرین سینک با تاریخ ارسالی تفاوت داشت، رکوردهای با تاریخ بالاتر از تاریخ ارسالی رو بفرست، در غیر اینصورت پیغام عددی بفرست که به برنامه بگه داده ها سینک هستن
نتیجه به کلاینت بر میگرده، اگه داده ی جدید ارسال شده اون رو به دیتابیس اضافه کن (INSERT و یا UPDATE) و تاریخ سینک رو برای رکورد ست کن (بر اساس تاریخ سرور)، اگر هم پیغام خطا ارسال شده بود مدیریتش کن
بعد چک کن ببین داده ای برای ارسال به سرور وجود داره ؟ (رکوردهایی که تاریخ سینک نخوردن)، اگه بود ارسالشون کن (و اگه سرور گفت دریافتشون کرده، تاریخ سینک رو براشون ست کن)


فکر کنم کل پروسه این بود.

البته این اولین پروژه ی اندروید و اولین پروژه ی PHP من بود و می دونم که راه های بسیار بهینه تری هست، ولی خب من دیگه بیشتر و بعد از اون روش کار نکردم.

reza_azizi2010
یک شنبه 21 اردیبهشت 1393, 19:12 عصر
خب اینجوری من باید هر دفعه کل رکوردها رو بررسی کنم تا ببینم تغییر کرده یا نه. و این کارو هم باید توی سرور انجام بدم هم توی گوشی
و مشکل دیگه هم اینه که تعداد رکوردهای دیتابیس یکبار موقع پرکردن مشخص میشه و دیگه تغییر نمیکنه و ثابت هست، فقط بعضی مقادیر تغییر میکنه.

poorman
یک شنبه 21 اردیبهشت 1393, 19:33 عصر
من هیچی از سرور و اینجور چیزا نمیدونم، ولی توی این مورد آخر میتونم یکم نظر بدم

اینکه یک فیلد تغییر داشته باشید و بعد از هر بار تغییر اون رو true کنید، بعد وقتی خواستید سینک کنید رکوردهایی رو select میکنید که true هستن

و بعد از سینک شدن همه رکوردها false میشن

Nevercom
یک شنبه 21 اردیبهشت 1393, 19:40 عصر
عرض کردم، اینکار رو با ست کردن تاریخ سینک روی رکورد انجام دادم، محتویات رکورد رو بررسی نمیکنم، اما تضمین می کنم با هر تغییری فیلد تاریخ آپدیت بشه
هنگام ارسال هم آخرین تاریخ رو میفرستم و مقایسه رو براساس آخرین تاریخ انجام میدم که کوئری های بسیار سبکی هستن.

به هرحال لزوم انجام فرآیند سینک این هست که شما معیاری از تغییر بین دو دیتابیس و نسخه های مختلف داده ها داشته باشید.
میتونید این معیار رو یک تگ مثل تاریخ درنظر بگیرید، میتونید معیار رو محتوای رکورد (یا داده) بگیرید، مثلاً یک هش که معرف اون داده باشه

به هرحال شاید این تجربیات بتونه کمک کنه به روشی برسید که خیلی بهینه تر باشه.

reza_azizi2010
یک شنبه 21 اردیبهشت 1393, 22:04 عصر
من دنبال یک راه حل اصولی بودم، پس با این حساب الگوریتم خاصی وجود نداره و هرکسی با توجه به منطق برنامه اش یه روشی استفاده میکنه؟

Nevercom
دوشنبه 22 اردیبهشت 1393, 01:21 صبح
اجازه بدید این موضوع رو کمی بیشتر باز کنم.

یک روش کلی و یک الگوریتم استاندارد برای سینک وجود نداره، دلیلش هم اینه که بنا به نیازهای پروژه نیاز هست از راهکارهای متفاوتی استفاده کنید.
اما در حالت کلی هر الگوریتم سینک باید بتونه اینها رو مدیریت کنه:

افزوده شدن رکورد به دیتابیس
حدف رکورد از دیتابیس
تغییرات رکوردها یا همون آپدیت

مسئله ی بسیار مهم تر و البته پیچیده تر بحث Conflict یا مغایرت داده ها هست. این قسمت هم پیچیدگی های زیادی داره.
پس دنبال یه الگوریتم آماده که بی نقص باشه، نباشید، در عوض بنا به نیازهای خودتون الگوریتم سینک رو پیاده سازی کنید.

شما باید در الگوریتمون مشخص کنید که ارزش کدوم داده بیشتر هست، سرور یا کلاینت. به زبان ساده تر مشخص کنید که اگه تو دیتابیس لوکال یه محصول تعدادش ۵ تا بود و تو سرور ۳ تا، کدوم یک از این داده ها معتبرتر هست، باید اطلاعات سرور تغییر کنه و بشه ۵ تا یا اطلاعات لوکال نادیده گرفته بشه و به ۳ تا تقلیل پیدا کنه.

باید روشی مناسب برای مقایسه ی داده ها انتخاب کنید که با پردازش کمتر، با دقت بالاتری تشخیص بده که داده ها سینک هستن یا خیر.

بر اساس نیازتون ببینید که آیا بحث همزمانی برای شما پیش میاد یا خیر، یعنی چقدر احتمال داره در عرض یک ثانیه چند نسخه از یک رکورد مشخص به سرور ارسال بشه، این مورد مهم هست و باید مورد توجه قرار بگیره، اما اگر احتمال خیلی زیادی وجود داره که این همزمانی داده ها اتفاق نیفته (چون میگید ۱۰ تا کلاینت دارید)، شاید بهتر باشه این موضوع رو موکول کنید به زمانی که توان فنی و مالیش رو داشته باشید که همگام با شرکت هایی مثل دراپ باکس پیش برید. در این حالت باید تصمیم بگیرید که واکنش سرور نسبت به دریافت نسخه ی جدید از یک داده، در زمانی که نسخه ای دیگه درحال ثبت شدن هست چی باشه، آیا باید داده جدید رو رد کنه، جایگزین کنه، با یک تگ مشخص کنه که داده Conflict داره و ....، مثلاً دراپ باکس در زمان Conflict نسخه های مختلف رو ذخیره می کنه، برای هر کاربر نسخه ی خودش رو بعنوان نسخه ی اصلی درنطر میگیره و بقیه ی نسخه های یک فایل که Conflict دارن رو Rename میکنه.

با اینکه عرض کردم روش پیش نهادی اولین تجربه ی من بوده، اما با تحقیق و البته بر اساس نیاز اون زمان شرکت شکل گرفته.

این سیستم رو من برای نگهداری داده هایی که متعلق به یک کاربر هست نوشتم که بتونه همیشه و روی دستگاه های مختلف همون داده ها رو داشته باشه و بتونه تغییرشون بده
در این سیستم هیچ رکوردی بصورت دائمی حذف نمیشه (چون داده ای هست که معادل ریالی داره و ارزشمند هست) و بجای حذف، از دید پنهان میشه.

روشی که من انتخاب کرده بودم این بود که داده های سرور همیشه با ارزش تر هستند پس همیشه اول داده های سرور رو دریافت کردم و کلاینت رو آپدیت کردم
بدلیل ماهیت تک کاربره بودن - یعنی کاربر روی موبایل داده رو تغییر میده و مثلاً روی دستگاه دیگه همون تغییرات رو بتونه دریافت کنه و بتونه تغییر بده، اما بطور همزمان از چند دستگاه تغییر صورت نمیگیره - روی بحث همزمانی کار نکرده بودم.

روش تشخیص تغییرات دو دیتابیس هم بر اساس یک تگ زمانی از جنس Timestamp با دقت میلی ثانیه بود که شرحش رو خدمتتون عرض کردم، این روش شاید بهترین روش نباشه اما قطعاً یک روش اصولی و منطقی هست (و البته تقریباً سبک از نطر پردازشی)
بعنوان مثال روش مشابه روشی که من استفاده کرده بودم رو می تونید اینجا ببینید: http://havrl.blogspot.com/2013/08/synchronization-algorithm-for.html
یا این تحقیق آکادمیک در مورد سینک به روش Versioning بعنوان یک راه حل دیگه رو بررسی کنید: https://docs.google.com/file/d/0B1E0IqcKw1t9R2hLVTdkTGVJaXc/edit

موضوع اینه که سینک کردن داده ها پیچیدگی هایی رو همراه خودش داره که تنها راه برطرف کردنشون شناخت دقیق نیازهای پروژه ی خودتون هست.