HBase-аас унших хурдыг 3 дахин, HDFS-ээс 5 дахин нэмэгдүүлэх арга

Өндөр гүйцэтгэл нь том өгөгдөлтэй ажиллахад тавигдах гол шаардлагуудын нэг юм. Сбербанкны өгөгдөл ачаалах хэлтэст бид бараг бүх гүйлгээг Hadoop-д суурилсан Data Cloud руу шахдаг тул маш их мэдээллийн урсгалтай ажилладаг. Мэдээжийн хэрэг, бид гүйцэтгэлийг сайжруулах арга замыг үргэлж хайж байдаг бөгөөд одоо бид RegionServer HBase болон HDFS клиентийг хэрхэн нөхөж чадсаныг танд хэлэхийг хүсч байна, үүний ачаар бид унших үйлдлийн хурдыг мэдэгдэхүйц нэмэгдүүлэх боломжтой болсон.
HBase-аас унших хурдыг 3 дахин, HDFS-ээс 5 дахин нэмэгдүүлэх арга

Гэсэн хэдий ч сайжруулалтын мөн чанарт шилжихээсээ өмнө хатуу диск дээр суувал зарчмын хувьд тойрч гарах боломжгүй хязгаарлалтуудын талаар ярих нь зүйтэй.

Яагаад HDD болон хурдан санамсаргүй хандалтын уншилтууд таарахгүй байна вэ?
Таны мэдэж байгаагаар HBase болон бусад олон мэдээллийн сан нь өгөгдлийг хэдэн арван килобайт хэмжээтэй блокуудад хадгалдаг. Анхдагчаар энэ нь ойролцоогоор 64 КБ байна. Одоо бид зөвхөн 100 байт авах хэрэгтэй гэж төсөөлөөд үз дээ, бид HBase-ээс тодорхой түлхүүр ашиглан энэ өгөгдлийг бидэнд өгөхийг хүсч байна. HFiles дахь блокийн хэмжээ 64 KB тул хүсэлт нь шаардлагатай хэмжээнээс 640 дахин их (ердөө нэг минут!) байх болно.

Дараа нь, хүсэлт нь HDFS болон түүний мета өгөгдлийг кэшлэх механизмаар дамжих тул ShortCircuitCache (файл руу шууд хандах боломжийг олгодог) энэ нь дискнээс аль хэдийн 1 МБ уншихад хүргэдэг. Гэхдээ үүнийг параметрийн тусламжтайгаар тохируулж болно dfs.клиент.унших.богино холболт.буфер.хэмжээ мөн ихэнх тохиолдолд энэ утгыг жишээлбэл 126 KB болгон бууруулах нь зүйтэй юм.

Бид үүнийг хийдэг гэж бодъё, гэхдээ үүнээс гадна FileChannel.read гэх мэт функцууд гэх мэт java api-ээр дамжуулан өгөгдлийг уншиж эхлэхэд үйлдлийн системээс заасан хэмжээний өгөгдлийг уншихыг хүсэхэд "ямар ч тохиолдолд" 2 дахин их уншдаг. , өөрөөр хэлбэл Манай тохиолдолд 256 KB. Учир нь java-д энэ үйлдлээс урьдчилан сэргийлэхийн тулд FADV_RANDOM тугийг тохируулах хялбар арга байдаггүй.

Үүний үр дүнд бидний 100 байтыг авахын тулд бүрээсний доор 2600 дахин их уншдаг. Шийдэл нь ойлгомжтой юм шиг санагдаж, блокны хэмжээг нэг килобайт болгон багасгаж, дурдсан тугийг байрлуулж, гэгээрлийн их хурдыг олж авцгаая. Гэхдээ асуудал нь блокийн хэмжээг 2 дахин бууруулснаар бид цаг хугацааны нэгжид унших байтуудын тоог 2 дахин багасгадаг.

FADV_RANDOM тугийг тохируулснаар тодорхой хэмжээний ашиг авч болно, гэхдээ зөвхөн өндөр олон урсгалтай, 128 KB блокийн хэмжээтэй байх боловч энэ нь хамгийн ихдээ хэдэн арван хувь юм:

HBase-аас унших хурдыг 3 дахин, HDFS-ээс 5 дахин нэмэгдүүлэх арга

Туршилтыг тус бүр нь 100 ГБ хэмжээтэй, 1 HDD дээр байрлуулсан 10 файл дээр хийсэн.

Энэ хурдаар зарчмын хувьд юунд найдаж болохыг тооцоолъё.
Бид 10 дискнээс 280 МБ/сек хурдтайгаар уншсан гэж бодъё, өөрөөр хэлбэл. 3 сая дахин 100 байт. Гэхдээ бидний санаж байгаагаар бидэнд хэрэгтэй өгөгдөл нь уншсанаас 2600 дахин бага байдаг. Ингээд 3 саяыг 2600-д хуваагаад авна Секундэд 1100 бичлэг.

Сэтгэлээр унасан, тийм үү? Ийм л байгаль Санамсаргүй хандалт HDD дээрх өгөгдөлд хандах - блокийн хэмжээнээс үл хамааран. Энэ бол санамсаргүй хандалтын физик хязгаар бөгөөд ийм нөхцөлд ямар ч мэдээллийн сан илүү шахагдаж чадахгүй.

Өгөгдлийн сангууд хэрхэн илүү өндөр хурдтай ажилладаг вэ? Энэ асуултад хариулахын тулд дараах зураг дээр юу болж байгааг харцгаая.

HBase-аас унших хурдыг 3 дахин, HDFS-ээс 5 дахин нэмэгдүүлэх арга

Эндээс бид эхний хэдэн минутын хурд нь секундэд мянга орчим рекорд болохыг харж байна. Гэсэн хэдий ч, хүссэн хэмжээнээс хамаагүй ихийг уншдаг тул өгөгдөл нь үйлдлийн системийн (linux) buff/кэшт дуусч, хурд нь секундэд 60 мянга болж өсдөг.

Тиймээс бид зөвхөн үйлдлийн системийн кэшэд байгаа эсвэл SSD/NVMe хадгалах төхөөрөмжид байгаа өгөгдөлд хандах хандалтыг хурдасгах асуудлыг шийдвэрлэх болно.

Манай тохиолдолд бид 4 серверийн вандан сандал дээр туршилт хийх бөгөөд тус бүр нь дараах байдлаар цэнэглэгддэг.

CPU: Xeon E5-2680 v4 @ 2.40GHz 64 урсгалтай.
Санах ой: 730 ГБ.
java хувилбар: 1.8.0_111

Энд гол зүйл бол унших шаардлагатай хүснэгтүүдийн өгөгдлийн хэмжээ юм. Үнэн хэрэгтээ хэрэв та HBase кэшэд бүрэн байрлуулсан хүснэгтээс өгөгдлийг уншвал тэр нь үйлдлийн системийн buff/cache-ээс унших боломжгүй болно. Учир нь HBase анхдагчаар санах ойн 40%-ийг BlockCache хэмээх бүтцэд хуваарилдаг. Үндсэндээ энэ нь ConcurrentHashMap бөгөөд гол нь файлын нэр + блокийн офсет бөгөөд утга нь энэ офсет дээрх бодит өгөгдөл юм.

Тиймээс зөвхөн энэ бүтцээс уншихад бид Бид гайхалтай хурдыг харж байна, секундэд нэг сая хүсэлт гэх мэт. Гэхдээ эдгээр серверүүд дээр өөр олон хэрэгтэй зүйл байдаг тул бид зөвхөн мэдээллийн сангийн хэрэгцээнд зориулж хэдэн зуун гигабайт санах ойг хуваарилж чадахгүй гэж төсөөлөөд үз дээ.

Жишээлбэл, манай тохиолдолд нэг RS дээрх BlockCache-ийн хэмжээ 12 ГБ орчим байна. Бид нэг зангилаа дээр хоёр RS газардсан, i.e. Бүх зангилаанууд дээр BlockCache-д 96 ГБ хуваарилагдсан. Үүнээс хэд дахин илүү өгөгдөл байдаг, жишээлбэл, 4 хүснэгт, тус бүр нь 130 бүс, файлууд нь 800 МБ хэмжээтэй, FAST_DIFF-ээр шахагдсан, өөрөөр хэлбэл. нийт 410 ГБ (энэ нь цэвэр өгөгдөл, өөрөөр хэлбэл хуулбарлах хүчин зүйлийг тооцохгүйгээр).

Тиймээс, BlockCache нь нийт өгөгдлийн эзлэхүүний дөнгөж 23 орчим хувийг эзэлдэг бөгөөд энэ нь BigData гэж нэрлэгддэг бодит нөхцөлтэй илүү ойр байдаг. Эндээс л зугаа цэнгэл эхэлдэг - учир нь кэш бага байх тусам гүйцэтгэл муу байх нь ойлгомжтой. Эцсийн эцэст, хэрэв та алдвал та маш их ажил хийх хэрэгтэй болно - өөрөөр хэлбэл. Системийн функцуудыг дуудах руу очно уу. Гэсэн хэдий ч үүнээс зайлсхийх боломжгүй тул огт өөр талыг харцгаая - кэш доторх өгөгдөлд юу тохиолдох вэ?

Нөхцөл байдлыг хялбаршуулж, бид зөвхөн 1 объектод тохирох кэштэй гэж үзье. Бид кэшээс 3 дахин их өгөгдлийн эзэлхүүнтэй ажиллахыг оролдоход юу болох жишээг энд үзүүлэв:

1. Блок 1-ийг кэшэд байрлуул
2. 1-р блокыг кэшээс устгана уу
3. Блок 2-ийг кэшэд байрлуул
4. 2-р блокыг кэшээс устгана уу
5. Блок 3-ийг кэшэд байрлуул

5 үйлдэл дууссан! Гэсэн хэдий ч энэ нөхцөл байдлыг хэвийн гэж нэрлэж болохгүй, үнэндээ бид HBase-г олон тооны ашиггүй ажил хийхийг албадаж байна. Энэ нь OS-ийн кэшээс өгөгдлийг байнга уншиж, BlockCache-д байрлуулдаг бөгөөд өгөгдлийн шинэ хэсэг ирсэн тул бараг тэр даруй хаядаг. Нийтлэлийн эхэнд байгаа хөдөлгөөнт дүрс нь асуудлын мөн чанарыг харуулж байна - Хог цуглуулагч цар хүрээгээ алдаж, уур амьсгал халж, алс холын халуун Шведэд бяцхан Грета бухимдаж байна. Мэдээллийн технологийн салбарынхан бид хүүхдүүд гунигтай байх үед үнэхээр дургүй байдаг тул бид энэ талаар юу хийж болох талаар бодож эхэлдэг.

Хэрэв та кэшийг дүүргэхгүйн тулд бүх блокуудыг биш, харин зөвхөн тодорхой хувийг нь оруулбал яах вэ? BlockCache-д өгөгдөл оруулах функцийн эхэнд хэдхэн мөр код нэмж оруулаад эхэлцгээе.

  public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf, boolean inMemory) {
    if (cacheDataBlockPercent != 100 && buf.getBlockType().isData()) {
      if (cacheKey.getOffset() % 100 >= cacheDataBlockPercent) {
        return;
      }
    }
...

Энд гол зүйл бол: офсет нь файл дахь блокийн байрлал бөгөөд түүний сүүлчийн цифрүүд 00-ээс 99 хүртэл санамсаргүй бөгөөд жигд тархсан байдаг. Тиймээс бид зөвхөн шаардлагатай мужид багтах тоог алгасах болно.

Жишээлбэл, cacheDataBlockPercent = 20 гэж тохируулаад юу болохыг хараарай:

HBase-аас унших хурдыг 3 дахин, HDFS-ээс 5 дахин нэмэгдүүлэх арга

Үр дүн нь ойлгомжтой. Доорх графикуудаас харахад яагаад ийм хурдатгал гарсан нь тодорхой болж байна - бид ангарагийн нохойнуудын урсац руу шууд хаяхын тулд өгөгдлийг кэшэд байршуулах Sisyphean ажлыг хийлгүйгээр GC-ийн маш их нөөцийг хэмнэдэг.

HBase-аас унших хурдыг 3 дахин, HDFS-ээс 5 дахин нэмэгдүүлэх арга

Үүний зэрэгцээ CPU-ийн ашиглалт нэмэгдэж байгаа боловч бүтээмжээс хамаагүй бага байна:

HBase-аас унших хурдыг 3 дахин, HDFS-ээс 5 дахин нэмэгдүүлэх арга

BlockCache-д хадгалагдсан блокууд өөр өөр байдаг гэдгийг тэмдэглэх нь зүйтэй. Ихэнх нь, ойролцоогоор 95% нь өөрөө өгөгдөл юм. Үлдсэн хэсэг нь Bloom filters эсвэл LEAF_INDEX гэх мэт мета өгөгдөл юм гэх мэт.. Энэ өгөгдөл хангалтгүй, гэхдээ энэ нь маш хэрэгтэй, учир нь өгөгдөлд шууд хандахын өмнө HBase мета руу эргэж, энд цаашид хайх шаардлагатай эсэх, хэрэв тийм бол сонирхлын блок яг хаана байрлаж байгааг ойлгох болно.

Тиймээс кодонд бид шалгах нөхцөлийг харж байна buf.getBlockType().isData() мөн энэ метаны ачаар бид үүнийг ямар ч тохиолдолд кэшэд үлдээх болно.

Одоо ачааллыг нэмэгдүүлж, функцийг нэг дор бага зэрэг чангалцгаая. Эхний туршилтанд бид хязгаарын хувийг = 20 болгосон ба BlockCache бага зэрэг ашиглагдаагүй. Одоо үүнийг 23% болгож, 100 минут тутамд 5 утсыг нэмж, ханасан байдал ямар цэг дээр гарч байгааг харцгаая.

HBase-аас унших хурдыг 3 дахин, HDFS-ээс 5 дахин нэмэгдүүлэх арга

Эндээс бид анхны хувилбар нь секундэд 100 мянган хүсэлтээр бараг тэр даруй таазанд хүрч байгааг харж байна. Харин нөхөөс нь 300 мянга хүртэлх хурдатгал өгдөг. Үүний зэрэгцээ, цаашдын хурдатгал нь "үнэгүй" байхаа больсон нь тодорхой байна; CPU-ийн хэрэглээ мөн нэмэгдэж байна.

Гэсэн хэдий ч энэ нь тийм ч гоёмсог шийдэл биш юм, учир нь бид блокуудын хэдэн хувийг кэш хийх шаардлагатайг урьдчилан мэдэхгүй тул ачааллын профайлаас хамаарна. Тиймээс унших үйл ажиллагааны идэвхжилээс хамааран энэ параметрийг автоматаар тохируулах механизмыг хэрэгжүүлсэн.

Үүнийг хянахын тулд гурван сонголтыг нэмсэн:

hbase.lru.cache.heavy.evction.count.limit — оновчлолыг ашиглаж эхлэхээс өмнө (жишээ нь блок алгасах) кэшээс өгөгдлийг арилгах үйл явц хэдэн удаа үргэлжлэх ёстойг тохируулдаг. Анхдагчаар энэ нь MAX_INT = 2147483647-тэй тэнцүү бөгөөд үнэндээ энэ функц хэзээ ч энэ утгаараа ажиллаж эхлэхгүй гэсэн үг юм. Учир нь нүүлгэн шилжүүлэх үйл явц 5 - 10 секунд тутамд эхэлдэг (энэ нь ачаалалаас хамаарна) ба 2147483647 * 10/60/60/24/365 = 680 жил. Гэсэн хэдий ч бид энэ параметрийг 0 болгож тохируулсны дараа функцийг ажиллуулсны дараа шууд ажиллах боломжтой.

Гэсэн хэдий ч энэ параметрт ачаалал бас бий. Хэрэв бидний ачаалал богино хугацааны уншлага (өдрийн цагаар гэх мэт) болон урт хугацааны уншилтууд (шөнийн цагаар) байнга тасалддаг бол бид зөвхөн урт унших ажиллагаа явагдаж байх үед функцийг асаасан эсэхийг шалгах боломжтой.

Жишээлбэл, богино хугацааны уншилт нь ихэвчлэн 1 минут орчим үргэлжилдэг гэдгийг бид мэднэ. Блокуудыг хаяж эхлэх шаардлагагүй, кэш хуучирч хоцрох цаг гарахгүй тул бид энэ параметрийг жишээлбэл 10-тай тэнцүүлж болно. Энэ нь оновчлол нь зөвхөн урт хугацааны дараа л ажиллаж эхлэхэд хүргэнэ. идэвхтэй унших хугацаа эхэлсэн, өөрөөр хэлбэл. 100 секундын дотор. Тиймээс, хэрэв бид богино хугацааны уншлагатай бол бүх блокууд кэш рүү орж, бэлэн байх болно (стандарт алгоритмаар хасагдахаас бусад). Мөн бид удаан хугацааны уншлага хийх үед функц идэвхждэг бөгөөд бид илүү өндөр гүйцэтгэлтэй байх болно.

hbase.lru.cache.heavy.evction.mb.size.хязгаар - 10 секундын дотор бид хэдэн мегабайтыг кэшэд байршуулахыг (мэдээжийн хэрэг, нүүлгэх) тохируулна. Онцлог нь энэ үнэ цэнэд хүрч, түүнийг хадгалахыг хичээх болно. Гол нь: хэрэв бид гигабайтыг кэш рүү оруулбал гигабайтыг зайлуулах шаардлагатай болно, энэ нь дээр дурдсанчлан маш үнэтэй юм. Гэсэн хэдий ч та үүнийг хэтэрхий жижиг болгохыг хичээх ёсгүй, учир нь энэ нь блок алгасах горимоос эрт гарахад хүргэдэг. Хүчирхэг серверүүдийн хувьд (ойролцоогоор 20-40 физик цөм) ойролцоогоор 300-400 MB тохируулах нь оновчтой байдаг. Дунд ангийн хувьд (~10 цөм) 200-300 MB. Сул системүүдийн хувьд (2-5 цөм) 50-100 МБ хэвийн байж болно (эдгээр дээр туршиж үзээгүй).

Энэ хэрхэн ажилладагийг харцгаая: hbase.lru.cache.heavy.eviction.mb.size.limit = 500 гэж тохирууллаа гэж бодъё, ямар нэгэн ачаалал (унших) байгаа бөгөөд дараа нь ~10 секунд тутамд бид хэдэн байт байсныг тооцоолно. томъёог ашиглан нүүлгэнэ:

Нэмэлт зардал = Чөлөөт байт нийлбэр (MB) * 100 / Хязгаар (MB) - 100;

Хэрэв үнэндээ 2000 МБ зайлуулсан бол нэмэлт зардал нь дараахтай тэнцүү байна.

2000 * 100 / 500 - 100 = 300%

Алгоритмууд нь хэдэн арван хувиас илүүгүй байлгахыг хичээдэг тул энэ функц нь кэштэй блокуудын хувийг бууруулж, автоматаар тохируулах механизмыг хэрэгжүүлэх болно.

Гэсэн хэдий ч, хэрэв ачаалал буурвал ердөө 200 МБ зайлуулж, Overhead сөрөг болж (хэт ачаалал гэж нэрлэгддэг) гэж үзье.

200 * 100 / 500 - 100 = -60%

Эсрэгээр, энэ функц нь нэмэлт ачаалал эерэг болох хүртэл кэшд хадгалагдсан блокуудын хувийг нэмэгдүүлэх болно.

Энэ нь бодит өгөгдөл дээр хэрхэн харагдах жишээг доор харуулав. 0% хүрэх гэж оролдох шаардлагагүй, боломжгүй юм. Ойролцоогоор 30 - 100% байх нь маш сайн бөгөөд энэ нь богино хугацааны өсөлтийн үед оновчлолын горимоос эрт гарахаас зайлсхийхэд тусалдаг.

hbase.lru.cache.хүнд.нүүлгэх.overhead.коэффициент - бид үр дүндээ хэр хурдан хүрэхийг хүсч байгаагаа тодорхойлдог. Хэрэв бидний унших хугацаа ихэвчлэн урт бөгөөд хүлээхийг хүсэхгүй байгаа гэдгийг баттай мэдэж байвал бид энэ харьцааг нэмэгдүүлж, өндөр гүйцэтгэлийг хурдан авах боломжтой.

Жишээлбэл, бид энэ коэффициентийг = 0.01 гэж тогтоосон. Энэ нь нэмэлт зардал (дээрхийг харна уу) үр дүнгийн үр дүнд энэ тоогоор үржиж, кэштэй блокуудын хувь багасна гэсэн үг юм. Overhead = 300% ба коэффициент = 0.01 гэж бодъё, тэгвэл кэштэй блокуудын хувь 3% -иар буурна.

Үүнтэй төстэй "Буцах даралт" логикийг сөрөг Overhead (хэт давах) утгуудад мөн хэрэгжүүлдэг. Уншсан болон нүүлгэн шилжүүлэлтийн эзлэхүүний богино хугацааны хэлбэлзэл үргэлж боломжтой байдаг тул энэ механизм нь оновчтой горимоос эрт гарахаас зайлсхийх боломжийг олгодог. Буцах даралт нь урвуу логиктой: хэт их ачаалал өгөх тусам илүү олон блок кэш болно.

HBase-аас унших хурдыг 3 дахин, HDFS-ээс 5 дахин нэмэгдүүлэх арга

Хэрэгжүүлэх код

        LruBlockCache cache = this.cache.get();
        if (cache == null) {
          break;
        }
        freedSumMb += cache.evict()/1024/1024;
        /*
        * Sometimes we are reading more data than can fit into BlockCache
        * and it is the cause a high rate of evictions.
        * This in turn leads to heavy Garbage Collector works.
        * So a lot of blocks put into BlockCache but never read,
        * but spending a lot of CPU resources.
        * Here we will analyze how many bytes were freed and decide
        * decide whether the time has come to reduce amount of caching blocks.
        * It help avoid put too many blocks into BlockCache
        * when evict() works very active and save CPU for other jobs.
        * More delails: https://issues.apache.org/jira/browse/HBASE-23887
        */

        // First of all we have to control how much time
        // has passed since previuos evict() was launched
        // This is should be almost the same time (+/- 10s)
        // because we get comparable volumes of freed bytes each time.
        // 10s because this is default period to run evict() (see above this.wait)
        long stopTime = System.currentTimeMillis();
        if ((stopTime - startTime) > 1000 * 10 - 1) {
          // Here we have to calc what situation we have got.
          // We have the limit "hbase.lru.cache.heavy.eviction.bytes.size.limit"
          // and can calculte overhead on it.
          // We will use this information to decide,
          // how to change percent of caching blocks.
          freedDataOverheadPercent =
            (int) (freedSumMb * 100 / cache.heavyEvictionMbSizeLimit) - 100;
          if (freedSumMb > cache.heavyEvictionMbSizeLimit) {
            // Now we are in the situation when we are above the limit
            // But maybe we are going to ignore it because it will end quite soon
            heavyEvictionCount++;
            if (heavyEvictionCount > cache.heavyEvictionCountLimit) {
              // It is going for a long time and we have to reduce of caching
              // blocks now. So we calculate here how many blocks we want to skip.
              // It depends on:
             // 1. Overhead - if overhead is big we could more aggressive
              // reducing amount of caching blocks.
              // 2. How fast we want to get the result. If we know that our
              // heavy reading for a long time, we don't want to wait and can
              // increase the coefficient and get good performance quite soon.
              // But if we don't sure we can do it slowly and it could prevent
              // premature exit from this mode. So, when the coefficient is
              // higher we can get better performance when heavy reading is stable.
              // But when reading is changing we can adjust to it and set
              // the coefficient to lower value.
              int change =
                (int) (freedDataOverheadPercent * cache.heavyEvictionOverheadCoefficient);
              // But practice shows that 15% of reducing is quite enough.
              // We are not greedy (it could lead to premature exit).
              change = Math.min(15, change);
              change = Math.max(0, change); // I think it will never happen but check for sure
              // So this is the key point, here we are reducing % of caching blocks
              cache.cacheDataBlockPercent -= change;
              // If we go down too deep we have to stop here, 1% any way should be.
              cache.cacheDataBlockPercent = Math.max(1, cache.cacheDataBlockPercent);
            }
          } else {
            // Well, we have got overshooting.
            // Mayby it is just short-term fluctuation and we can stay in this mode.
            // It help avoid permature exit during short-term fluctuation.
            // If overshooting less than 90%, we will try to increase the percent of
            // caching blocks and hope it is enough.
            if (freedSumMb >= cache.heavyEvictionMbSizeLimit * 0.1) {
              // Simple logic: more overshooting - more caching blocks (backpressure)
              int change = (int) (-freedDataOverheadPercent * 0.1 + 1);
              cache.cacheDataBlockPercent += change;
              // But it can't be more then 100%, so check it.
              cache.cacheDataBlockPercent = Math.min(100, cache.cacheDataBlockPercent);
            } else {
              // Looks like heavy reading is over.
              // Just exit form this mode.
              heavyEvictionCount = 0;
              cache.cacheDataBlockPercent = 100;
            }
          }
          LOG.info("BlockCache evicted (MB): {}, overhead (%): {}, " +
            "heavy eviction counter: {}, " +
            "current caching DataBlock (%): {}",
            freedSumMb, freedDataOverheadPercent,
            heavyEvictionCount, cache.cacheDataBlockPercent);

          freedSumMb = 0;
          startTime = stopTime;
       }

Одоо энэ бүгдийг бодит жишээ ашиглан харцгаая. Бидэнд дараах туршилтын скрипт байна:

  1. Скан хийж эхэлцгээе (25 хэлхээ, багц = 100)
  2. 5 минутын дараа олон авах (25 хэлхээ, багц = 100) нэмнэ үү.
  3. 5 минутын дараа multi-get-г унтраа (зөвхөн скан дахин үлдэнэ)

Бид хоёр гүйлт хийдэг, эхлээд hbase.lru.cache.heavy.eviction.count.limit = 10000 (энэ нь уг функцийг идэвхгүй болгодог), дараа нь хязгаарыг = 0 (үүнийг идэвхжүүлдэг) тохируулна.

Доорх логууд дээр бид функц хэрхэн асаалттай байгааг харж, Overshooting-ийг 14-71% болгон дахин тохируулж байна. Үе үе ачаалал багасдаг бөгөөд энэ нь Backpressure болон HBase дахин олон блокуудыг кэш болгодог.

Бүртгэлийн сервер
нүүлгэгдсэн (MB): 0, харьцаа 0.0, нэмэлт зардал (%): -100, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 0, одоогийн кэш DataBlock (%): 100
нүүлгэгдсэн (MB): 0, харьцаа 0.0, нэмэлт зардал (%): -100, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 0, одоогийн кэш DataBlock (%): 100
нүүлгэгдсэн (MB): 2170, харьцаа 1.09, нэмэлт зардал (%): 985, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 1, одоогийн кэш DataBlock (%): 91 < эхлэл
нүүлгэгдсэн (MB): 3763, харьцаа 1.08, нэмэлт зардал (%): 1781, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 2, одоогийн кэш DataBlock (%): 76
нүүлгэгдсэн (MB): 3306, харьцаа 1.07, нэмэлт зардал (%): 1553, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 3, одоогийн кэш DataBlock (%): 61
нүүлгэгдсэн (MB): 2508, харьцаа 1.06, нэмэлт зардал (%): 1154, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 4, одоогийн кэш DataBlock (%): 50
нүүлгэгдсэн (MB): 1824, харьцаа 1.04, нэмэлт зардал (%): 812, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 5, одоогийн кэш DataBlock (%): 42
нүүлгэгдсэн (MB): 1482, харьцаа 1.03, нэмэлт зардал (%): 641, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 6, одоогийн кэш DataBlock (%): 36
нүүлгэгдсэн (MB): 1140, харьцаа 1.01, нэмэлт зардал (%): 470, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 7, одоогийн кэш DataBlock (%): 32
нүүлгэгдсэн (MB): 913, харьцаа 1.0, нэмэлт зардал (%): 356, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 8, одоогийн кэш DataBlock (%): 29
нүүлгэгдсэн (MB): 912, харьцаа 0.89, нэмэлт зардал (%): 356, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 9, одоогийн кэш DataBlock (%): 26
нүүлгэгдсэн (MB): 684, харьцаа 0.76, нэмэлт зардал (%): 242, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 10, одоогийн кэш DataBlock (%): 24
нүүлгэгдсэн (MB): 684, харьцаа 0.61, нэмэлт зардал (%): 242, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 11, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 456, харьцаа 0.51, нэмэлт зардал (%): 128, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 12, одоогийн кэш DataBlock (%): 21
нүүлгэгдсэн (MB): 456, харьцаа 0.42, нэмэлт зардал (%): 128, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 13, одоогийн кэш DataBlock (%): 20
нүүлгэгдсэн (MB): 456, харьцаа 0.33, нэмэлт зардал (%): 128, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 14, одоогийн кэш DataBlock (%): 19
нүүлгэгдсэн (MB): 342, харьцаа 0.33, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 15, одоогийн кэш DataBlock (%): 19
нүүлгэгдсэн (MB): 342, харьцаа 0.32, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 16, одоогийн кэш DataBlock (%): 19
нүүлгэгдсэн (MB): 342, харьцаа 0.31, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 17, одоогийн кэш DataBlock (%): 19
нүүлгэгдсэн (MB): 228, харьцаа 0.3, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 18, одоогийн кэш DataBlock (%): 19
нүүлгэгдсэн (MB): 228, харьцаа 0.29, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 19, одоогийн кэш DataBlock (%): 19
нүүлгэгдсэн (MB): 228, харьцаа 0.27, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 20, одоогийн кэш DataBlock (%): 19
нүүлгэгдсэн (MB): 228, харьцаа 0.25, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 21, одоогийн кэш DataBlock (%): 19
нүүлгэгдсэн (MB): 228, харьцаа 0.24, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 22, одоогийн кэш DataBlock (%): 19
нүүлгэгдсэн (MB): 228, харьцаа 0.22, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 23, одоогийн кэш DataBlock (%): 19
нүүлгэгдсэн (MB): 228, харьцаа 0.21, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 24, одоогийн кэш DataBlock (%): 19
нүүлгэгдсэн (MB): 228, харьцаа 0.2, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 25, одоогийн кэш DataBlock (%): 19
нүүлгэгдсэн (MB): 228, харьцаа 0.17, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 26, одоогийн кэш DataBlock (%): 19
нүүлгэгдсэн (MB): 456, харьцаа 0.17, нэмэлт зардал (%): 128, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 27, одоогийн кэш DataBlock (%): 18 < нэмэгдсэн авсан (гэхдээ хүснэгт ижил)
нүүлгэгдсэн (MB): 456, харьцаа 0.15, нэмэлт зардал (%): 128, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 28, одоогийн кэш DataBlock (%): 17
нүүлгэгдсэн (MB): 342, харьцаа 0.13, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 29, одоогийн кэш DataBlock (%): 17
нүүлгэгдсэн (MB): 342, харьцаа 0.11, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 30, одоогийн кэш DataBlock (%): 17
нүүлгэгдсэн (MB): 342, харьцаа 0.09, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 31, одоогийн кэш DataBlock (%): 17
нүүлгэгдсэн (MB): 228, харьцаа 0.08, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 32, одоогийн кэш DataBlock (%): 17
нүүлгэгдсэн (MB): 228, харьцаа 0.07, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 33, одоогийн кэш DataBlock (%): 17
нүүлгэгдсэн (MB): 228, харьцаа 0.06, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 34, одоогийн кэш DataBlock (%): 17
нүүлгэгдсэн (MB): 228, харьцаа 0.05, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 35, одоогийн кэш DataBlock (%): 17
нүүлгэгдсэн (MB): 228, харьцаа 0.05, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 36, одоогийн кэш DataBlock (%): 17
нүүлгэгдсэн (MB): 228, харьцаа 0.04, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 37, одоогийн кэш DataBlock (%): 17
нүүлгэгдсэн (MB): 109, харьцаа 0.04, нэмэлт зардал (%): -46, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 37, одоогийн кэш DataBlock (%): 22 < арын даралт
нүүлгэгдсэн (MB): 798, харьцаа 0.24, нэмэлт зардал (%): 299, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 38, одоогийн кэш DataBlock (%): 20
нүүлгэгдсэн (MB): 798, харьцаа 0.29, нэмэлт зардал (%): 299, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 39, одоогийн кэш DataBlock (%): 18
нүүлгэгдсэн (MB): 570, харьцаа 0.27, нэмэлт зардал (%): 185, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 40, одоогийн кэш DataBlock (%): 17
нүүлгэгдсэн (MB): 456, харьцаа 0.22, нэмэлт зардал (%): 128, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 41, одоогийн кэш DataBlock (%): 16
нүүлгэгдсэн (MB): 342, харьцаа 0.16, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 42, одоогийн кэш DataBlock (%): 16
нүүлгэгдсэн (MB): 342, харьцаа 0.11, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 43, одоогийн кэш DataBlock (%): 16
нүүлгэгдсэн (MB): 228, харьцаа 0.09, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 44, одоогийн кэш DataBlock (%): 16
нүүлгэгдсэн (MB): 228, харьцаа 0.07, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 45, одоогийн кэш DataBlock (%): 16
нүүлгэгдсэн (MB): 228, харьцаа 0.05, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 46, одоогийн кэш DataBlock (%): 16
нүүлгэгдсэн (MB): 222, харьцаа 0.04, нэмэлт зардал (%): 11, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 47, одоогийн кэш DataBlock (%): 16
нүүлгэгдсэн (MB): 104, харьцаа 0.03, нэмэлт зардал (%): -48, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 47, одоогийн кэш DataBlock (%): 21 < тасалдал авдаг
нүүлгэгдсэн (MB): 684, харьцаа 0.2, нэмэлт зардал (%): 242, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 48, одоогийн кэш DataBlock (%): 19
нүүлгэгдсэн (MB): 570, харьцаа 0.23, нэмэлт зардал (%): 185, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 49, одоогийн кэш DataBlock (%): 18
нүүлгэгдсэн (MB): 342, харьцаа 0.22, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 50, одоогийн кэш DataBlock (%): 18
нүүлгэгдсэн (MB): 228, харьцаа 0.21, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 51, одоогийн кэш DataBlock (%): 18
нүүлгэгдсэн (MB): 228, харьцаа 0.2, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 52, одоогийн кэш DataBlock (%): 18
нүүлгэгдсэн (MB): 228, харьцаа 0.18, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 53, одоогийн кэш DataBlock (%): 18
нүүлгэгдсэн (MB): 228, харьцаа 0.16, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 54, одоогийн кэш DataBlock (%): 18
нүүлгэгдсэн (MB): 228, харьцаа 0.14, нэмэлт зардал (%): 14, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 55, одоогийн кэш DataBlock (%): 18
нүүлгэгдсэн (MB): 112, харьцаа 0.14, нэмэлт зардал (%): -44, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 55, одоогийн кэш DataBlock (%): 23 < арын даралт
нүүлгэгдсэн (MB): 456, харьцаа 0.26, нэмэлт зардал (%): 128, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 56, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.31, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 57, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.33, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 58, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.33, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 59, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.33, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 60, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.33, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 61, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.33, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 62, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.33, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 63, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.32, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 64, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.33, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 65, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.33, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 66, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.32, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 67, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.33, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 68, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.32, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 69, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.32, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 70, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.33, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 71, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.33, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 72, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.33, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 73, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.33, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 74, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.33, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 75, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 342, харьцаа 0.33, нэмэлт зардал (%): 71, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 76, одоогийн кэш DataBlock (%): 22
нүүлгэгдсэн (MB): 21, харьцаа 0.33, нэмэлт зардал (%): -90, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 76, одоогийн кэш DataBlock (%): 32
нүүлгэгдсэн (MB): 0, харьцаа 0.0, нэмэлт зардал (%): -100, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 0, одоогийн кэш DataBlock (%): 100
нүүлгэгдсэн (MB): 0, харьцаа 0.0, нэмэлт зардал (%): -100, хүнд нүүлгэн шилжүүлэлтийн тоолуур: 0, одоогийн кэш DataBlock (%): 100

Нэг (өмнө нь хэзээ ч хүсэлт гаргаж байгаагүй блокууд) ба олон (дор хаяж нэг удаа "хүссэн" өгөгдөл энд хадгалагддаг) гэсэн хоёр кэш хэсгийн хоорондын хамаарлын график хэлбэрээр ижил процессыг харуулахын тулд сканнердах шаардлагатай байв.

HBase-аас унших хурдыг 3 дахин, HDFS-ээс 5 дахин нэмэгдүүлэх арга

Эцэст нь, параметрүүдийн ажиллагаа график хэлбэрээр ямар харагдаж байна. Харьцуулбал, кэшийг эхэндээ бүрэн унтраасан, дараа нь HBase-ийг кэштэй ажиллуулж, оновчлолын ажлыг эхлүүлэхийг 5 минут (30 нүүлгэн шилжүүлэх цикл) хойшлуулав.

Бүрэн кодыг татах хүсэлтээс олж болно HBASE 23887 github дээр.

Гэсэн хэдий ч, секундэд 300 мянган унших нь эдгээр нөхцөлд энэ техник хангамж дээр хүрч болох бүх зүйл биш юм. HDFS-ээр дамжуулан өгөгдөлд хандах шаардлагатай үед ShortCircuitCache (цаашид SSC гэх) механизмыг ашигладаг бөгөөд энэ нь сүлжээний харилцан үйлчлэлээс зайлсхийж өгөгдөлд шууд хандах боломжийг олгодог.

Профайлаас харахад энэ механизм нь ихээхэн ашиг өгдөг ч зарим үед түгжрэл үүсгэдэг, учир нь бараг бүх хүнд үйлдлүүд цоож дотор явагддаг бөгөөд энэ нь ихэнх тохиолдолд түгжрэлд хүргэдэг.

HBase-аас унших хурдыг 3 дахин, HDFS-ээс 5 дахин нэмэгдүүлэх арга

Үүнийг ойлгосноор бид олон тооны бие даасан SSC-үүдийг бий болгосноор асуудлыг тойрч болно гэдгийг ойлгосон.

private final ShortCircuitCache[] shortCircuitCache;
...
shortCircuitCache = new ShortCircuitCache[this.clientShortCircuitNum];
for (int i = 0; i < this.clientShortCircuitNum; i++)
  this.shortCircuitCache[i] = new ShortCircuitCache(…);

Дараа нь хамгийн сүүлийн офсет цифр дээрх уулзваруудыг эс тооцвол тэдэнтэй ажиллана уу:

public ShortCircuitCache getShortCircuitCache(long idx) {
    return shortCircuitCache[(int) (idx % clientShortCircuitNum)];
}

Одоо та туршилтаа эхлүүлж болно. Үүнийг хийхийн тулд бид HDFS-ээс файлуудыг энгийн олон урсгалтай програмаар унших болно. Параметрүүдийг тохируулна уу:

conf.set("dfs.client.read.shortcircuit", "true");
conf.set("dfs.client.read.shortcircuit.buffer.size", "65536"); // по дефолту = 1 МБ и это сильно замедляет чтение, поэтому лучше привести в соответствие к реальным нуждам
conf.set("dfs.client.short.circuit.num", num); // от 1 до 10

Тэгээд зүгээр л файлуудыг уншина уу:

FSDataInputStream in = fileSystem.open(path);
for (int i = 0; i < count; i++) {
    position += 65536;
    if (position > 900000000)
        position = 0L;
    int res = in.read(position, byteBuffer, 0, 65536);
}

Энэ кодыг тусдаа хэлхээнд гүйцэтгэдэг бөгөөд бид нэгэн зэрэг уншдаг файлуудын тоо (10-аас 200 - хэвтээ тэнхлэг) болон кэшийн тоог (1-ээс 10 хүртэл - график) нэмэгдүүлэх болно. Босоо тэнхлэг нь зөвхөн нэг кэш байгаа тохиолдолд SSC-ийн өсөлтөөс үүсэх хурдатгалыг харуулдаг.

HBase-аас унших хурдыг 3 дахин, HDFS-ээс 5 дахин нэмэгдүүлэх арга

Графикийг хэрхэн унших вэ: Нэг кэштэй 100 KB блок дахь 64 мянган уншлагад 78 секунд шаардлагатай. Харин 5 кэштэй бол 16 секунд болно. Тэдгээр. ~5 дахин хурдатгал байна. Графикаас харахад цөөн тооны зэрэгцээ уншихад нөлөө нь тийм ч мэдэгдэхүйц биш, 50 гаруй утас уншсан үед мэдэгдэхүйц үүрэг гүйцэтгэж эхэлдэг.Мөн SSC-ийн тоог 6-аас нэмэгдүүлж байгаа нь ажиглагдаж байна. ба түүнээс дээш үзүүлэлт нь гүйцэтгэлийн мэдэгдэхүйц өсөлтийг өгдөг.

Тайлбар 1: Туршилтын үр дүн нэлээд тогтворгүй байгаа тул (доороос үзнэ үү) 3 удаа гүйлт хийж, үр дүнгийн утгыг дундажлав.

Тайлбар 2: Хандалт өөрөө бага зэрэг удааширсан хэдий ч санамсаргүй хандалтыг тохируулснаар гүйцэтгэлийн өсөлт ижил байна.

Гэсэн хэдий ч HBase-ийн тохиолдлоос ялгаатай нь энэ хурдатгал нь үргэлж үнэ төлбөргүй байдаггүй гэдгийг тодруулах шаардлагатай. Энд бид төв процессорыг түгжээнд зүүхийн оронд илүү их ажиллах чадварыг "нээдэг".

HBase-аас унших хурдыг 3 дахин, HDFS-ээс 5 дахин нэмэгдүүлэх арга

Ерөнхийдөө кэшийн тоо нэмэгдэх нь CPU-ийн ашиглалтыг ойролцоогоор пропорциональ хэмжээгээр нэмэгдүүлж байгааг эндээс харж болно. Гэсэн хэдий ч арай илүү ялалтын хослолууд байдаг.

Жишээлбэл, SSC = 3 тохиргоог нарийвчлан авч үзье. Хүрээ дээрх гүйцэтгэлийн өсөлт нь ойролцоогоор 3.3 дахин байна. Гурван тусдаа гүйлтийн үр дүнг доор харуулав.

HBase-аас унших хурдыг 3 дахин, HDFS-ээс 5 дахин нэмэгдүүлэх арга

Харин CPU-ийн хэрэглээ ойролцоогоор 2.8 дахин нэмэгддэг. Ялгаа нь тийм ч том биш ч бяцхан Грета аль хэдийн баяртай байгаа бөгөөд сургуульд сурч, хичээлээ үзэх цаг гаргаж магадгүй юм.

Тиймээс энэ нь програмын код нь хөнгөн (жишээ нь, залгуур нь HDFS клиент талд байгаа) болон CPU-ийн үнэгүй тэжээлтэй байх тохиолдолд HDFS-д бөөнөөр ханддаг аливаа хэрэгсэлд эерэг нөлөө үзүүлэх болно (жишээ нь Spark гэх мэт). . Үүнийг шалгахын тулд HBase-ээс уншихад BlockCache оновчлол болон SSC тохируулгыг хослуулан хэрэглэх нь ямар нөлөө үзүүлэхийг туршиж үзье.

HBase-аас унших хурдыг 3 дахин, HDFS-ээс 5 дахин нэмэгдүүлэх арга

Ийм нөхцөлд үр нөлөө нь боловсронгуй туршилтынх шиг тийм ч их биш (ямар ч боловсруулалтгүйгээр унших) байгааг харж болно, гэхдээ энд нэмэлт 80К шахах боломжтой. Хоёр оновчлол нь хамтдаа 4 дахин хурдасгах боломжийг олгодог.

Энэ оновчлолд зориулж PR ч хийсэн [HDFS-15202], нэгтгэсэн бөгөөд энэ функц нь дараагийн хувилбаруудад боломжтой болно.

Эцэст нь Кассандра ба HBase зэрэг өргөн баганын мэдээллийн баазын унших чадварыг харьцуулах нь сонирхолтой байлаа.

Үүнийг хийхийн тулд бид хоёр хостоос (нийт 800 утас) YCSB ачааллын тестийн стандарт хэрэгслийн жишээг эхлүүлсэн. Сервер талд - 4 хост дээр RegionServer болон Cassandra-ийн 4 тохиолдол (нөлөөлөлөөс зайлсхийхийн тулд үйлчлүүлэгчид ажиллаж байгаа биш). Хэмжээний хүснэгтээс уншилтууд гарсан:

HBase – HDFS дээр 300 ГБ (100 ГБ цэвэр өгөгдөл)

Кассандра - 250 ГБ (хуулбарлах хүчин зүйл = 3)

Тэдгээр. эзлэхүүн нь ойролцоогоор ижил байсан (HBase дээр арай илүү).

HBase параметрүүд:

dfs.client.short.circuit.num = 5 (HDFS үйлчлүүлэгчийн оновчлол)

hbase.lru.cache.heavy.evction.count.limit = 30 - энэ нь нөхөөс нь 30 нүүлгэсний дараа ажиллаж эхэлнэ гэсэн үг (~5 минут)

hbase.lru.cache.heavy.evition.mb.size.limit = 300 - кэш хийх, нүүлгэх зорилтот хэмжээ

YCSB бүртгэлийг задлан шинжилж, Excel график болгон эмхэтгэсэн:

HBase-аас унших хурдыг 3 дахин, HDFS-ээс 5 дахин нэмэгдүүлэх арга

Таны харж байгаагаар эдгээр оновчлол нь эдгээр өгөгдлийн сангийн гүйцэтгэлийг эдгээр нөхцөлд харьцуулж, секундэд 450 мянган уншихад хүрэх боломжийг олгодог.

Энэхүү мэдээлэл нь бүтээмжийн төлөөх сэтгэл хөдөлгөм тэмцлийн үеэр хэн нэгэнд хэрэг болно гэж найдаж байна.

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх