mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2025-02-09 15:27:11 +00:00
lib/storage: follow-up for 790768f20b
- Document the bugfix at docs/CHANGELOG.md - Simplify the bugfix a bit
This commit is contained in:
parent
be78950011
commit
d3035b1ca1
3 changed files with 79 additions and 27 deletions
|
@ -15,6 +15,8 @@ The following tip changes can be tested by building VictoriaMetrics components f
|
||||||
|
|
||||||
## tip
|
## tip
|
||||||
|
|
||||||
|
* BUGFIX: properly register new time series in per-day inverted index if they were ingested during the last 10 seconds of the day. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3309). Thanks to @lmarszal for the bugreport and for the [initial fix](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/3320).
|
||||||
|
|
||||||
|
|
||||||
## [v1.83.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.83.0)
|
## [v1.83.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.83.0)
|
||||||
|
|
||||||
|
|
|
@ -715,10 +715,12 @@ func (s *Storage) currHourMetricIDsUpdater() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-s.stop:
|
case <-s.stop:
|
||||||
s.updateCurrHourMetricIDs()
|
hour := fasttime.UnixHour()
|
||||||
|
s.updateCurrHourMetricIDs(hour)
|
||||||
return
|
return
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
s.updateCurrHourMetricIDs()
|
hour := fasttime.UnixHour()
|
||||||
|
s.updateCurrHourMetricIDs(hour)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -731,10 +733,12 @@ func (s *Storage) nextDayMetricIDsUpdater() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-s.stop:
|
case <-s.stop:
|
||||||
s.updateNextDayMetricIDs()
|
date := fasttime.UnixDate()
|
||||||
|
s.updateNextDayMetricIDs(date)
|
||||||
return
|
return
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
s.updateNextDayMetricIDs()
|
date := fasttime.UnixDate()
|
||||||
|
s.updateNextDayMetricIDs(date)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2411,8 +2415,7 @@ type byDateMetricIDEntry struct {
|
||||||
v uint64set.Set
|
v uint64set.Set
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) updateNextDayMetricIDs() {
|
func (s *Storage) updateNextDayMetricIDs(date uint64) {
|
||||||
date := fasttime.UnixDate()
|
|
||||||
e := s.nextDayMetricIDs.Load().(*byDateMetricIDEntry)
|
e := s.nextDayMetricIDs.Load().(*byDateMetricIDEntry)
|
||||||
s.pendingNextDayMetricIDsLock.Lock()
|
s.pendingNextDayMetricIDsLock.Lock()
|
||||||
pendingMetricIDs := s.pendingNextDayMetricIDs
|
pendingMetricIDs := s.pendingNextDayMetricIDs
|
||||||
|
@ -2426,6 +2429,11 @@ func (s *Storage) updateNextDayMetricIDs() {
|
||||||
// Slow path: union pendingMetricIDs with e.v
|
// Slow path: union pendingMetricIDs with e.v
|
||||||
if e.date == date {
|
if e.date == date {
|
||||||
pendingMetricIDs.Union(&e.v)
|
pendingMetricIDs.Union(&e.v)
|
||||||
|
} else {
|
||||||
|
// Do not add pendingMetricIDs from the previous day to the cyrrent day,
|
||||||
|
// since this may result in missing registration of the metricIDs in the per-day inverted index.
|
||||||
|
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3309
|
||||||
|
pendingMetricIDs = &uint64set.Set{}
|
||||||
}
|
}
|
||||||
eNew := &byDateMetricIDEntry{
|
eNew := &byDateMetricIDEntry{
|
||||||
date: date,
|
date: date,
|
||||||
|
@ -2434,7 +2442,7 @@ func (s *Storage) updateNextDayMetricIDs() {
|
||||||
s.nextDayMetricIDs.Store(eNew)
|
s.nextDayMetricIDs.Store(eNew)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) updateCurrHourMetricIDs() {
|
func (s *Storage) updateCurrHourMetricIDs(hour uint64) {
|
||||||
hm := s.currHourMetricIDs.Load().(*hourMetricIDs)
|
hm := s.currHourMetricIDs.Load().(*hourMetricIDs)
|
||||||
var newEntries []pendingHourMetricIDEntry
|
var newEntries []pendingHourMetricIDEntry
|
||||||
s.pendingHourEntriesLock.Lock()
|
s.pendingHourEntriesLock.Lock()
|
||||||
|
@ -2453,7 +2461,6 @@ func (s *Storage) updateCurrHourMetricIDs() {
|
||||||
}
|
}
|
||||||
s.pendingHourEntriesLock.Unlock()
|
s.pendingHourEntriesLock.Unlock()
|
||||||
|
|
||||||
hour := fasttime.UnixHour()
|
|
||||||
if len(newEntries) == 0 && hm.hour == hour {
|
if len(newEntries) == 0 && hm.hour == hour {
|
||||||
// Fast path: nothing to update.
|
// Fast path: nothing to update.
|
||||||
return
|
return
|
||||||
|
@ -2473,18 +2480,23 @@ func (s *Storage) updateCurrHourMetricIDs() {
|
||||||
byTenant = make(map[accountProjectKey]*uint64set.Set)
|
byTenant = make(map[accountProjectKey]*uint64set.Set)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, x := range newEntries {
|
if hour%24 != 0 {
|
||||||
m.Add(x.MetricID)
|
// Do not add pending metricIDs from the previous hour to the current hour on the next day,
|
||||||
k := accountProjectKey{
|
// since this may result in missing registration of the metricIDs in the per-day inverted index.
|
||||||
AccountID: x.AccountID,
|
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3309
|
||||||
ProjectID: x.ProjectID,
|
for _, x := range newEntries {
|
||||||
|
m.Add(x.MetricID)
|
||||||
|
k := accountProjectKey{
|
||||||
|
AccountID: x.AccountID,
|
||||||
|
ProjectID: x.ProjectID,
|
||||||
|
}
|
||||||
|
e := byTenant[k]
|
||||||
|
if e == nil {
|
||||||
|
e = &uint64set.Set{}
|
||||||
|
byTenant[k] = e
|
||||||
|
}
|
||||||
|
e.Add(x.MetricID)
|
||||||
}
|
}
|
||||||
e := byTenant[k]
|
|
||||||
if e == nil {
|
|
||||||
e = &uint64set.Set{}
|
|
||||||
byTenant[k] = e
|
|
||||||
}
|
|
||||||
e.Add(x.MetricID)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hmNew := &hourMetricIDs{
|
hmNew := &hourMetricIDs{
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"testing/quick"
|
"testing/quick"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fasttime"
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/uint64set"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/uint64set"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -154,7 +155,7 @@ func TestUpdateCurrHourMetricIDs(t *testing.T) {
|
||||||
}
|
}
|
||||||
t.Run("empty_pending_metric_ids_stale_curr_hour", func(t *testing.T) {
|
t.Run("empty_pending_metric_ids_stale_curr_hour", func(t *testing.T) {
|
||||||
s := newStorage()
|
s := newStorage()
|
||||||
hour := uint64(timestampFromTime(time.Now())) / msecPerHour
|
hour := fasttime.UnixHour()
|
||||||
hmOrig := &hourMetricIDs{
|
hmOrig := &hourMetricIDs{
|
||||||
m: &uint64set.Set{},
|
m: &uint64set.Set{},
|
||||||
hour: 123,
|
hour: 123,
|
||||||
|
@ -162,7 +163,7 @@ func TestUpdateCurrHourMetricIDs(t *testing.T) {
|
||||||
hmOrig.m.Add(12)
|
hmOrig.m.Add(12)
|
||||||
hmOrig.m.Add(34)
|
hmOrig.m.Add(34)
|
||||||
s.currHourMetricIDs.Store(hmOrig)
|
s.currHourMetricIDs.Store(hmOrig)
|
||||||
s.updateCurrHourMetricIDs()
|
s.updateCurrHourMetricIDs(hour)
|
||||||
hmCurr := s.currHourMetricIDs.Load().(*hourMetricIDs)
|
hmCurr := s.currHourMetricIDs.Load().(*hourMetricIDs)
|
||||||
if hmCurr.hour != hour {
|
if hmCurr.hour != hour {
|
||||||
// It is possible new hour occurred. Update the hour and verify it again.
|
// It is possible new hour occurred. Update the hour and verify it again.
|
||||||
|
@ -186,7 +187,7 @@ func TestUpdateCurrHourMetricIDs(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("empty_pending_metric_ids_valid_curr_hour", func(t *testing.T) {
|
t.Run("empty_pending_metric_ids_valid_curr_hour", func(t *testing.T) {
|
||||||
s := newStorage()
|
s := newStorage()
|
||||||
hour := uint64(timestampFromTime(time.Now())) / msecPerHour
|
hour := fasttime.UnixHour()
|
||||||
hmOrig := &hourMetricIDs{
|
hmOrig := &hourMetricIDs{
|
||||||
m: &uint64set.Set{},
|
m: &uint64set.Set{},
|
||||||
hour: hour,
|
hour: hour,
|
||||||
|
@ -194,7 +195,7 @@ func TestUpdateCurrHourMetricIDs(t *testing.T) {
|
||||||
hmOrig.m.Add(12)
|
hmOrig.m.Add(12)
|
||||||
hmOrig.m.Add(34)
|
hmOrig.m.Add(34)
|
||||||
s.currHourMetricIDs.Store(hmOrig)
|
s.currHourMetricIDs.Store(hmOrig)
|
||||||
s.updateCurrHourMetricIDs()
|
s.updateCurrHourMetricIDs(hour)
|
||||||
hmCurr := s.currHourMetricIDs.Load().(*hourMetricIDs)
|
hmCurr := s.currHourMetricIDs.Load().(*hourMetricIDs)
|
||||||
if hmCurr.hour != hour {
|
if hmCurr.hour != hour {
|
||||||
// It is possible new hour occurred. Update the hour and verify it again.
|
// It is possible new hour occurred. Update the hour and verify it again.
|
||||||
|
@ -243,7 +244,7 @@ func TestUpdateCurrHourMetricIDs(t *testing.T) {
|
||||||
x.Add(e.MetricID)
|
x.Add(e.MetricID)
|
||||||
}
|
}
|
||||||
|
|
||||||
hour := uint64(timestampFromTime(time.Now())) / msecPerHour
|
hour := fasttime.UnixHour()
|
||||||
hmOrig := &hourMetricIDs{
|
hmOrig := &hourMetricIDs{
|
||||||
m: &uint64set.Set{},
|
m: &uint64set.Set{},
|
||||||
hour: 123,
|
hour: 123,
|
||||||
|
@ -251,7 +252,7 @@ func TestUpdateCurrHourMetricIDs(t *testing.T) {
|
||||||
hmOrig.m.Add(12)
|
hmOrig.m.Add(12)
|
||||||
hmOrig.m.Add(34)
|
hmOrig.m.Add(34)
|
||||||
s.currHourMetricIDs.Store(hmOrig)
|
s.currHourMetricIDs.Store(hmOrig)
|
||||||
s.updateCurrHourMetricIDs()
|
s.updateCurrHourMetricIDs(hour)
|
||||||
hmCurr := s.currHourMetricIDs.Load().(*hourMetricIDs)
|
hmCurr := s.currHourMetricIDs.Load().(*hourMetricIDs)
|
||||||
if hmCurr.hour != hour {
|
if hmCurr.hour != hour {
|
||||||
// It is possible new hour occurred. Update the hour and verify it again.
|
// It is possible new hour occurred. Update the hour and verify it again.
|
||||||
|
@ -300,7 +301,7 @@ func TestUpdateCurrHourMetricIDs(t *testing.T) {
|
||||||
x.Add(e.MetricID)
|
x.Add(e.MetricID)
|
||||||
}
|
}
|
||||||
|
|
||||||
hour := uint64(timestampFromTime(time.Now())) / msecPerHour
|
hour := fasttime.UnixHour()
|
||||||
hmOrig := &hourMetricIDs{
|
hmOrig := &hourMetricIDs{
|
||||||
m: &uint64set.Set{},
|
m: &uint64set.Set{},
|
||||||
hour: hour,
|
hour: hour,
|
||||||
|
@ -308,7 +309,7 @@ func TestUpdateCurrHourMetricIDs(t *testing.T) {
|
||||||
hmOrig.m.Add(12)
|
hmOrig.m.Add(12)
|
||||||
hmOrig.m.Add(34)
|
hmOrig.m.Add(34)
|
||||||
s.currHourMetricIDs.Store(hmOrig)
|
s.currHourMetricIDs.Store(hmOrig)
|
||||||
s.updateCurrHourMetricIDs()
|
s.updateCurrHourMetricIDs(hour)
|
||||||
hmCurr := s.currHourMetricIDs.Load().(*hourMetricIDs)
|
hmCurr := s.currHourMetricIDs.Load().(*hourMetricIDs)
|
||||||
if hmCurr.hour != hour {
|
if hmCurr.hour != hour {
|
||||||
// It is possible new hour occurred. Update the hour and verify it again.
|
// It is possible new hour occurred. Update the hour and verify it again.
|
||||||
|
@ -342,6 +343,43 @@ func TestUpdateCurrHourMetricIDs(t *testing.T) {
|
||||||
t.Fatalf("unexpected s.pendingHourEntries.Len(); got %d; want %d", len(s.pendingHourEntries), 0)
|
t.Fatalf("unexpected s.pendingHourEntries.Len(); got %d; want %d", len(s.pendingHourEntries), 0)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
t.Run("nonempty_pending_metric_ids_from_previous_hour_new_day", func(t *testing.T) {
|
||||||
|
s := newStorage()
|
||||||
|
|
||||||
|
hour := fasttime.UnixHour()
|
||||||
|
hour -= hour % 24
|
||||||
|
|
||||||
|
s.pendingHourEntries = []pendingHourMetricIDEntry{
|
||||||
|
{AccountID: 123, ProjectID: 431, MetricID: 343},
|
||||||
|
{AccountID: 123, ProjectID: 431, MetricID: 32424},
|
||||||
|
{AccountID: 1, ProjectID: 2, MetricID: 8293432},
|
||||||
|
}
|
||||||
|
|
||||||
|
hmOrig := &hourMetricIDs{
|
||||||
|
m: &uint64set.Set{},
|
||||||
|
hour: hour - 1,
|
||||||
|
}
|
||||||
|
s.currHourMetricIDs.Store(hmOrig)
|
||||||
|
s.updateCurrHourMetricIDs(hour)
|
||||||
|
hmCurr := s.currHourMetricIDs.Load().(*hourMetricIDs)
|
||||||
|
if hmCurr.hour != hour {
|
||||||
|
t.Fatalf("unexpected hmCurr.hour; got %d; want %d", hmCurr.hour, hour)
|
||||||
|
}
|
||||||
|
if hmCurr.m.Len() != 0 {
|
||||||
|
t.Fatalf("unexpected non-empty hmCurr.m; got %v", hmCurr.m.AppendTo(nil))
|
||||||
|
}
|
||||||
|
byTenantExpected := make(map[accountProjectKey]*uint64set.Set)
|
||||||
|
if !reflect.DeepEqual(hmCurr.byTenant, byTenantExpected) {
|
||||||
|
t.Fatalf("unexpected hmPrev.byTenant; got %v; want %v", hmCurr.byTenant, byTenantExpected)
|
||||||
|
}
|
||||||
|
hmPrev := s.prevHourMetricIDs.Load().(*hourMetricIDs)
|
||||||
|
if !reflect.DeepEqual(hmPrev, hmOrig) {
|
||||||
|
t.Fatalf("unexpected hmPrev; got %v; want %v", hmPrev, hmOrig)
|
||||||
|
}
|
||||||
|
if len(s.pendingHourEntries) != 0 {
|
||||||
|
t.Fatalf("unexpected s.pendingHourEntries.Len(); got %d; want %d", len(s.pendingHourEntries), 0)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMetricRowMarshalUnmarshal(t *testing.T) {
|
func TestMetricRowMarshalUnmarshal(t *testing.T) {
|
||||||
|
|
Loading…
Reference in a new issue