Непрерывный вход в систему с использованием Redis для программистов с крупных заводов

Введение в Redis

Redis (полное имя: Remote Dictionary Server) — это высокопроизводительная система хранения данных с открытым исходным кодом, которая является быстрой, гибкой и масштабируемой. Это система хранения структур данных на основе памяти, которую можно использовать в качестве базы данных, кэша и брокера сообщений.

Redis поддерживает различные структуры данных, включая строку, хэш, список, набор и отсортированный набор. Эти структуры данных предоставляют богатый набор рабочих команд, что позволяет разработчикам легко обрабатывать различные потребности в данных. Кроме того, Redis также предоставляет два метода сохранения, а именно создание снимков и добавление журналов (файл только для добавления, AOF). Метод моментального снимка записывает данные памяти Redis на диск в двоичном формате, а AOF обеспечивает постоянство путем добавления и записи команд операций Redis.

Redis также поддерживает модель публикации/подписки и может использоваться в качестве брокера сообщений. Издатели отправляют сообщения по назначенным каналам, а подписчики могут получать и обрабатывать эти сообщения. Этот шаблон полезен в таких сценариях, как создание коммуникаций в реальном времени, систем, управляемых событиями, и очередей сообщений. Кроме того, Redis также может обеспечить распределенное хранилище и высокую доступность данных за счет репликации и сегментирования «главный-подчиненный». Репликация «главный-подчиненный» позволяет копировать данные на несколько подчиненных узлов для обеспечения разделения чтения и записи и резервного копирования данных. Шардинг может распределять данные по нескольким узлам Redis для достижения горизонтального расширения и балансировки нагрузки.

Подробное объяснение случая

Далее давайте перейдем к делу и представим, как программисты крупных производителей используют Redis.Первый классический случай — непрерывный вход в систему.

Каждый должен быть знаком с проблемой непрерывного входа в систему. Логика заключается в том, что у пользователей есть одна возможность войти в систему каждый день. Если вход прерван, счетчик непрерывных входов вернется к 0. Определение непрерывного входа: вы должны войти в систему до 23:59:59 каждый день, а это значит, что время истечения срока действия ключа нужно установить на 0 часов послезавтра. Ниже приведен полный код, реализованный с помощью Golang+Redis:

package main

import (
	"context"
	"fmt"
	"github.com/go-redis/redis/v8"
	"strconv"
	"time"
)

var (
	RedisClient *redis.Client
	ctx         = context.Background()
)

const continuesCheckKey = "uid_%d" //存储到redis的key

func InitRedis() {
    
    
	rdb := redis.NewClient(&redis.Options{
    
    
		Addr: "127.0.0.1:6379",
	})
	RedisClient = rdb
}

func main() {
    
    

	InitRedis()
	//通过一些业务逻辑获取uid,这里为了方便演示,直接写死
	uid := 5201314
	Checkin(ctx, uid)
}

// Checkin 连续签到天数
func Checkin(ctx context.Context, uid int) {
    
    
	key := fmt.Sprintf(continuesCheckKey, uid)

	//用户在某一天内不能重复签到
	if exists, _ := RedisClient.Exists(ctx, key).Result(); exists == 1 {
    
    
		if ttl := RedisClient.TTL(ctx, key).Val(); ttl >= time.Duration(24)*time.Hour {
    
    
			fmt.Printf("用户[%d]今天已经签到过了\n", uid)
			return
		}
	}

	// 1. 连续签到数+1
	err := RedisClient.Incr(ctx, key).Err()
	if err != nil {
    
    
		fmt.Printf("用户[%d]连续签到失败", uid)
		return
	} else {
    
    
		expAt := beginningOfDay().Add(48 * time.Hour)
		// 2. 设置签到记录在后天的0点到期
		if err := RedisClient.ExpireAt(ctx, key, expAt).Err(); err != nil {
    
    
			panic(err)
		} else {
    
    
			// 3. 打印用户续签后的连续签到天数
			day, err := getUserCheckInDays(ctx, uid)
			if err != nil {
    
    
				panic(err)
			}
			fmt.Printf("用户[%d]连续签到:%d(天), 过期时间:%s", uid, day, expAt.Format("2006-01-02 15:04:05"))
		}
	}
}

// getUserCheckInDays 获取用户连续签到天数
func getUserCheckInDays(ctx context.Context, userID int) (int, error) {
    
    
	key := fmt.Sprintf(continuesCheckKey, userID)
	days, err := RedisClient.Get(ctx, key).Result()
	if err != nil {
    
    
		return 0, err
	} else {
    
    
		return strconv.Atoi(days)
	}
}

// beginningOfDay 获取今天0点时间
func beginningOfDay() time.Time {
    
    
	now := time.Now()
	y, m, d := now.Date()
	return time.Date(y, m, d, 0, 0, 0, 0, time.Local)
}

Объяснение и анализ:

  1. Импортный пакет:
    • context: Предоставляет контекст для обработки сроков обработки запросов, сигналов отмены и т. д.
    • fmt: используется для форматированного вывода.
    • strconv: используется для преобразования между строками и базовыми типами данных.
    • time: Используется для операций, связанных со временем.
    • github.com/redis/go-redis/v9: это клиентская библиотека Redis на языке Go.
  2. Глобальные переменные и константы:
    • RedisClient: Клиент, используемый для взаимодействия с базой данных Redis.
    • ctx: глобальная контекстная переменная.
    • continuesCheckKey: шаблон постоянной строки, используемый для создания имени ключа данных регистрации пользователей, хранящихся в Redis.
  3. init()функция:
    • Инициализируйте клиентское соединение Redis и подключитесь к локальному серверу Redis.
  4. main()функция:
    • Для демонстрации напрямую прописывается идентификатор пользователя (5201314), а затем Checkin()вызывается функция.
  5. Checkin()функция:
    • Принимает контекст и идентификатор пользователя в качестве параметров.
    • Создайте имя ключа для входа пользователя key.
    • Проверьте, вошел ли пользователь в систему сегодня. Если пользователь вошел в систему, определите, прошло ли более 24 часов с момента последнего входа в систему. Если да, это означает, что пользователь вошел в систему сегодня и не будет обрабатывать его снова .
    • Если пользователь не выполнил вход, срок действия записи входа рассчитывается expAtкак 48 часов после полуночи сегодняшнего дня. Используйте Incr()команду, чтобы увеличить последовательный номер регистрации пользователя и установить срок действия expAt.
    • Вызовите getUserCheckInDays()функцию, чтобы получить количество последовательных дней регистрации пользователя и отформатировать выходные данные.
  6. getUserCheckInDays()функция:
    • Создайте имя ключа данных для входа на основе идентификатора пользователя key.
    • Используйте Get()команду, чтобы получить количество последовательных дней регистрации пользователя (хранится в строковой форме).
    • Используйте strconv.Atoi()для преобразования полученной строки в целое число и возврата ее.
  7. beginningOfDay()функция:
    • Возвращает нулевое время текущей даты.

おすすめ

転載: blog.csdn.net/m0_63230155/article/details/132262860