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

دو سامانه یک رویداد را ثبت میکنند و دو زمان متفاوت میدهند. تاریخنگار میگوید پمپ در ۱۴:۳۲:۰۶ تریپ کرد، گزارش رویداد اسکادا میگوید ۱۴:۳۲:۰۴ و دستور کار سامانه نگهداری میگوید ۱۴:۳۱. از کسی خواسته میشود این اختلاف را توضیح دهد و بررسی متوقف میماند، چون پیش از آنکه بتوان درباره آنچه رخ داده استدلال کرد باید معلوم شود چه چیزی زودتر رخ داده است. این یکی از رایجترین نقصهای داده صنعتی است و تقریبا هیچوقت از خرابی حسگر نمیآید.
علت معمول این است که کسی تصمیم نگرفته برچسب زمانی از کدام ساعت میآید. یک قرائت واحد دستکم از چهار ساعت عبور میکند: کنترلر یا حسگری که نمونه را برداشته، گیتویای که آن را دریافت کرده، کارگزار یا واسط برنامهنویسی که آن را بلعیده و پایگاه دادهای که سطر را نوشته است. هرکدام ساعتی دارند و هرکدام میتوانند رکورد را مهر زمان بزنند. اگر خط لوله داده صریح نگوید کدام مهر معتبر است، پاسخ همان مولفهای خواهد بود که آخرین توسعهدهنده دستکاری کرده، و میان دو مسیری که داده یکسان را حمل میکنند فرق خواهد داشت.
قاعده را ساده میتوان گفت: زمان نمونه تا حد ممکن نزدیک به خود اندازهگیری ثبت میشود و بدون تغییر، برای همیشه، همراه داده سفر میکند. هر مولفه پاییندستی که برچسب زمانی میخواهد، میدان خودش را اضافه میکند. نگه داشتن زمان دریافت در کنار زمان نمونه افزونگی نیست — تفاوت این دو تاخیر انتقال است که تشخیص واقعا مفیدی به دست میدهد، و به محض بازنویسی یکی از آن دو، دیگر بازیافتنی نیست.
این همه تنها وقتی به کار میآید که ساعت لبه درست باشد و اینجا پرسش دقت مطرح میشود. NTP روی یک شبکه محلی خوب شما را در حد چند میلیثانیه نگه میدارد؛ روی شبکه گسترده شلوغ یا لینک سلولی، دهها تا صدها میلیثانیه واقعبینانه است و مسیرهای نامتقارن نتیجه را به شکلی سوگیر میکنند که NTP توان تشخیصش را ندارد. این برای روندنگاری سطح یک مخزن کاملا کافی است و برای تحلیل توالی رویدادها کاملا ناکافی، جایی که تمام هدف تعیین این است که کدامیک از دو دستگاه حفاظتی زودتر عمل کرده است. اگر ترتیب در مقیاس میلیثانیه اهمیت دارد، پاسخ PTP با مهر زمانی سختافزاری در واسط شبکه است که روی بستر سوییچینگ درست پیکربندیشده به زیر یک میکروثانیه میرسد — و نکته مهم اینکه دقت را مهر زمانی سختافزاری میخرد، نه نام پروتکل روی برگه داده.
ساعتهای ارزان رانش دارند و حساب آن را دستکم میگیرند. یک کریستال معمول با بیست قسمت در میلیون مشخص میشود که یعنی یک و هفت دهم ثانیه در روز و حدود پنجاه ثانیه در ماه. دستگاهی که هنگام راهاندازی همگام میشود و دیگر هرگز نه، دستگاهی است که دادهاش تا پایان ماه یک دقیقه خطا دارد و این خطا آنقدر نرم انباشته میشود که کسی متوجه وقوعش نمیشود. بدتر، دستگاههایی هستند که اصلا ساعت بیدرنگ با پشتیبان باتری ندارند: در مبدا زمان یونیکس بالا میآیند، یا در آخرین زمانی که به آنها گفته شده، و هرچه میان روشن شدن و نخستین همگامسازی موفق بیرون میدهند برچسبی از ۱۹۷۰ یا از سهشنبه گذشته دارد. پرچم اعتبار زمان بگذارید، تلهمتری را تا انضباط ساعت نگه دارید، یا آن رکوردها را صراحتا علامت بزنید — اما نگذارید در قامت داده معمولی وارد تاریخنگار شوند.
منطقه زمانی گونه دیگری از خطا میسازد و راهحلش محل مناقشه نیست: همهجا UTC ذخیره کنید، تنها برای نمایش تبدیل کنید و هرگز زمان محلی را بدون اختلاف زمانی در ستون پایگاه داده ننویسید. حالت خرابیای که فراموش میشود ساعت مبهم پایان ساعت تابستانی است که در آن زمانهای محلی تکرار میشوند. یک ساعت داده که بر اساس زمان محلی مرتب شده به هم میریزد و بدتر، نیمی از آن ممکن است با سطرهای موجود روی کلید اصلیای که یکتایی زمان محلی را فرض کرده بود تصادم کند. هر سایتی که تغییر ساعت تابستانی دارد این نقص را سالی دو بار تولید میکند و سایتی که دولتش قاعده را عوض کند یک بار و بدون هشدار، وقتی پایگاه داده منطقههای زمانی سیستمعامل روی بعضی ماشینها بهروز شود و روی بعضی نه.
حساب بازهها هشدار جداگانهای میطلبد. مدتهایی که از تفریق دو قرائت ساعت دیواری به دست میآیند هر وقت ساعت میان آن دو پرش کند غلطاند و پرش دقیقا همان کاری است که تصحیح NTP پس از رانش دستگاه انجام میدهد. نتیجه میتواند منفی شود. برای زمان سپریشده از ساعت یکنواخت و برای زمان مطلق از ساعت دیواری استفاده کنید و هرگز این دو را مخلوط نکنید، چون شمارنده زمان اجرایی که گاهی بازه منفی گزارش میدهد ماهها به گردن حسگر انداخته میشود.
تفکیک، تله آرامتری است. اگر منبع با ده هرتز نمونه بردارد و انباره ثانیه کامل نگه دارد، ده رکورد روی یک برچسب زمانی جمع میشوند و هر مصرفکنندهای که یکتایی برچسب را فرض کند بیصدا یکی را نگه میدارد. اگر ترتیب درون ثانیه مهم است، یا جزء زیرثانیه را ذخیره کنید یا شماره ترتیبی برای هر دستگاه به عنوان معیار تفکیک حمل کنید. شماره ترتیب در هر حال ارزش دارد: از تصحیحهای ساعت جان سالم به در میبرد، تکراریهای ناشی از ارسال مجدد را قابل تشخیص میکند و تنها راه مطمئن اثبات این است که در قطعی شبکه چیزی گم نشده است.
جمع همه اینها مجموعه کوتاهی از تصمیمهاست که بهتر است یک بار گرفته و نوشته شوند. یک منبع زمان برای هر سایت، با هدف دقتی مستند که صادقانه از کاربرد داده استخراج شده باشد. زمان نمونه که در مبدا و به وقت UTC مهر میخورد و دستنخورده تا انتها میرود. زمان دریافت که در میدانی جدا نگه داشته میشود. یک شماره ترتیب برای هر دستگاه. یک پرچم اعتبار زمان برای پنجره پیش از همگامسازی. و هشداری روی انحراف ساعت، تا دستگاهِ در حال رانش خودش را اعلام کند نه اینکه وسط بررسی یک حادثه کشف شود، که گرانترین لحظه ممکن برای فهمیدن این است که برچسبهای زمانی شما هرگز قابل اعتماد نبودهاند.