Определение проблемы:
У нас есть это устройство IOT, каждое из которых отправляет нам журналы о местонахождении автомобилей. Мы хотим вычислить расстояние, на котором машина путешествует онлайн! поэтому, когда приходит журнал (после помещения его в очередь и т. д. c), мы делаем это:
type Delta struct {
DeviceId string
time int64
Distance float64
}
var LastLogs = make(map[string]FullLog)
var Distances = make(map[string]Delta)
func addLastLog(l FullLog) {
LastLogs[l.DeviceID] = l
}
func AddToLogPerDay(l FullLog) {
//mutex.Lock()
if val, ok := LastLogs[l.DeviceID]; ok {
if distance, exist := Distances[l.DeviceID]; exist {
x := computingDistance(val, l)
Distances[l.DeviceID] = Delta{
DeviceId: l.DeviceID,
time: distance.time + 1,
Distance: distance.Distance + x,
}
} else {
Distances[l.DeviceID] = Delta{
DeviceId: l.DeviceID,
time: 1,
Distance: 0,
}
}
}
addLastLog(l)
}
, который в основном вычисляет расстояние, используя функцию полезности! поэтому в Distances
каждый идентификатор устройства сопоставляется с некоторым пройденным расстоянием! теперь вот где начинается проблема: хотя эти расстояния добавляются к Distances map
, я хочу, чтобы подпрограмма go помещала эти данные в базу данных, но, поскольку существует много устройств и много журналов и так далее, выполняют этот запрос для каждого журнала. не очень хорошая идея Так что мне нужно это каждые 5 секунд, что означает, что каждые 5 секунд пытаться очистить список всех последних расстояний, добавленных на карту. Я написал эту функцию:
func UpdateLogPerDayTable() {
for {
for _, distance := range Distances {
logs := model.HourPerDay{}
result := services.CarDBProvider.DB.Table(model.HourPerDay{}.TableName()).
Where("created_at >? AND device_id = ?", getCurrentData(), distance.DeviceId).
Find(&logs)
if result.Error != nil && !result.RecordNotFound() {
log.Infof("Something went wrong while checking the log: %v", result.Error)
} else {
if !result.RecordNotFound() {
logs.CountDistance = distance.Distance
logs.CountSecond = distance.time
err := services.CarDBProvider.DB.Model(&logs).
Update(map[string]interface{}{
"count_second": logs.CountSecond,
"count_distance": logs.CountDistance,
})
if err.Error != nil {
log.Infof("Something went wrong while updating the log: %v", err.Error)
}
} else if result.RecordNotFound() {
dayLog := model.HourPerDay{
Model: gorm.Model{},
DeviceId: distance.DeviceId,
CountSecond: int64(distance.time),
CountDistance: distance.Distance,
}
err := services.CarDBProvider.DB.Create(&dayLog)
if err.Error != nil {
log.Infof("Something went wrong while adding the log: %v", err.Error)
}
}
}
}
time.Sleep(time.Second * 5)
}
}
она называется go utlis.UpdateLogPerDayTable()
в другой подпрограмме go. Однако здесь есть много проблем:
- Я не знаю, как обезопасить
Distances
, поэтому, когда я добавляю его в другую процедуру, я читаю его где-то еще, все в порядке! (Проблема в том, что что я хочу использовать go каналов и не знаю, как это сделать) - Как мне запланировать задачи в go для этой проблемы?
- Возможно, я добавлю Redis для хранения всех устройств, которые подключены к Интернету, чтобы я мог быстрее выполнять запрос выбора и просто обновлять фактическую базу данных. также добавьте время истечения для redis, так что если устройство не отправляло и данные в течение некоторого времени, оно исчезает! куда мне поместить этот код?
Извините, если моих объяснений было недостаточно, но мне действительно нужна помощь. специально для реализации кода