LINUX.ORG.RU

можно ли использовать только redis?

 


0

1

обычно redis используется как кеш к основной БД(реляционной). скажите, является ли хорошей практикой использовать только redis? то есть хранить в ней и критически важные данные, и не критически важные?

ведь есть же в redis команда bgsave, её можно пинать после каждой отправки данных

кроме того можно настроить конфиг redis так чтобы он периодически сохранял данные оперативной памяти на диск

разве этого всего недостаточно чтобы отказаться от «настоящей» БД типа postgres?

Мое оценочное суждение после нескольких дней знакомства - нет.

  1. База redis должна полностью умещаться в оперативной памяти, в отличии от обычных СУБД. Это значит что если у тебя 1м пользователей, из них активных 10к, а в день приходит 1к, все равно в оперативной памяти будут все их данные.

  2. В случае кластеризации каждый экземпляр должен содержать полную копию всех данных, которая должна умещаться в оперативку на каждом кластере.

  3. hset обновляется полностью.

  4. Нет update по условию.

  5. Из жабы не удобно работать, там даже тот уровень псевдо «транзакций» какой есть в redis, на уровне отправки команд, в популярной библиотеке не работает.

Из последних двух пунктов мне стало непонятно как сделать оптимистичную блокировку.

Теперь жду экспертов redis чтоб они меня поправили если я чего не понял.

anonymous ()
Ответ на: комментарий от anonymous

Даже так, пускай с учетом псевдо транзакций я не понимаю как сделать оптимистичную блокировку. Это невозможно, т.к. нет механизма проделать манипуляции с данными по условию, или наложить лок.

Я вот встречал мнение в инетах что можно обойтись только redis, но никто не раскал как.

anonymous ()
Ответ на: комментарий от anonymous

я поэтому и спрашиваю про лучшие практики. ведь одно дело, если я один «сравню», а другое дело, если «сравнит» армия разработчиков в течение нескольких лет

prozaik ()
Ответ на: комментарий от anonymous

непонятно как сделать оптимистичную блокировку

Инструкцию читать не пробовал? https://redis.io/topics/transactions#cas Кроме того есть lua-скрипты.

База redis должна полностью умещаться в оперативной памяти

Это фича и если кто-то хочет redis как основную базу, значит он хочет именно этого.

no-such-file ★★★★★ ()

ведь есть же в redis команда bgsave, её можно пинать после каждой отправки данных

Ничего пинать не надо, нужно включить AOF лог.

недостаточно чтобы отказаться от «настоящей» БД типа postgres?

ИМХО зависит больше от характера запросов. Без дополнительных средств что-то сложное хранить очень геморно, т.к. сложные данные придётся распихивать по примитивам руками и потом ещё городить на всё это запросы. Но можно использовать плагины, например Redisql и т.п.

no-such-file ★★★★★ ()
Ответ на: комментарий от prozaik

Тогда будет полезным уточнить критерии и требования.

Мне кажется редис, это дальнейшее развитие мемкэша (был опыт, но потом перешел на sqlite и сейчас ищутся альтернативы - редис тоже рассматривается). Здесь критичны персистентность, безопасность, скорость доступа, возможности нейминга, лицензионные политики, широта драйверов, «вес» зависимостей.

anonymous ()

Нет. Почему у тебя такие дурные мысли возникают? Может быть тебе просто хочется key-value DB? Ты лучше озвучь задачу, а коллективный разум предложит лучшее решение.

И опять не, Redis не (только) как кеш, а для хранения сессий и всевозможных неперсистентных данных, а ещё он умеет в pub-sub.

WitcherGeralt ★★ ()
Ответ на: комментарий от prozaik

Потому что. Свою задачку с логин-паролем ты решишь без вопросов, но развить в более сложную систему у тебя не выйдет – схема хранения не масштабируемая получится. То есть, даже не сама схема, а средства работы с этой схемой из приложения. Но в качестве обучения всё же рекомендую попробовать – я ведь тоже могу ошибаться.

webmonkey ()
Ответ на: комментарий от WitcherGeralt

чтобы не описывать сферического коня приведу конкретный код. с точки зрения вложенности и разбивки на подпрограммы он ужасен, но сейчас дело не в этом:

@app.route('/submit_notepad_request', methods=['POST'])
def submit_notepad_request():
    with DB_connection() as db_connect:
        notepad = request.values.get('notepad')
        id_auth_user = request.cookies.get('flask_adminka_authorized_user_id')

        db_cursor = db_connect.cursor()

        req = "select * from options where user_id=" + id_auth_user
        db_cursor.execute(req)
        record = db_cursor.fetchone() 

        if record:
            try: 
                req = "UPDATE options SET notepad='" + notepad + "' WHERE user_id=" + str(id_auth_user)
                db_cursor.execute(req);

                try:
                    with redis_instance.pipeline() as piper:
                        pipe.multi()
                        pipe.set('notepad:' + id_auth_user, notepad)
                        pipe.execute()
                        redis_instance.bgsave()
                except:
                    print('Log: redis error')
                    raise RedisSetOperationException

                db_connect.commit()

                resp = Response('submit notepad is complete')
                return resp
            except (RedisSetOperationException, psycopg2.OperationalError) as e:
                print('LOG: ', e)
                resp = Response('failed')
                return resp
        else:
            resp = Response('failed')
            return resp


class RedisSetOperationException(Exception):
    def __init__(self):
        print('redis set operation error occured')

есть некоторое текстовое поле ‘notepad’, данные котрого нужно сохранить в postgres и в redis таким образом чтобы не случилось так, что при отказе одного из серверов(при записи или при чтении), пользователь получил неактуальные данные.

здесь я попытался объединить две транзакции в одну. удачно ли получилось?

prozaik ()
Ответ на: комментарий от prozaik

Тебе нужно почитать про SQL injections. Зачем эта конструкция для редиса вместо просто set мне не ясно, думаю, что оно там не нужно. Ещё всегда делай except Exeption: вместо except:, чтобы не перехватывать SystemExit. К тому же неплохо бы сделать явный rollback.

WitcherGeralt ★★ ()
Ответ на: комментарий от WitcherGeralt

Но вообще, подумай, нужен ли тебе redis в принципе. На небольших объёмах данных и достаточной памяти под кеши для БД, особой разницы между postgre и редисом ты не обнаружишь. Скорее всего ты оверинженерингом увлёкся.

WitcherGeralt ★★ ()
Ответ на: комментарий от prozaik

Ну, тогда развлекайся. В принципе всё нормально, только инъекции не допускай, форматируй текст силами библиотеки, а не вручную.

В зависимости от библиотеки это будет выглядеть так:

  • db_cursor.execute('UPDATE options SET notepad=%s WHERE user_id=%s', notepad, id_auth_user)
  • db_cursor.execute('UPDATE options SET notepad=? WHERE user_id=?', (notepad, id_auth_user))
  • db_cursor.execute('UPDATE options SET notepad=:notepad WHERE user_id=:user', {'notepad': notepad, 'user': id_auth_user})
WitcherGeralt ★★ ()
Ответ на: комментарий от prozaik

bgsave после каждого изменения данных в редисе, серьезно? Ты же понимаешь, что он пишет на диск вообще все данные хранящиеся в редисе, а не только измененные? Если так хочется in memory key-value базу и с персистентностью включи aof в redis и убери bgsave либо вообще возьми tarantool. С транзакционностью проблемка тоже, если не пройдет коммит в sql-базу, то будет неконсистентность - в редисе одни данные(новые), а в sql - другие(старые). Хранить в куках голый идентификатор пользователя в базе - моветон. И там опечатка piper/pipe

anonymous ()
Ответ на: комментарий от prozaik

Если идентификатор пользователя это обычный автоинкрементный счетчик, можно просто перебирать пользоваетелй, подставляя на клиенте(браузере) нужное значение в куки. Если идентификатор выбирает пользователь(допустим это логин), то можно перебирать пользователей по словарю. Если это случайный набор символов достаточно большой длинны, то его можно перехватить и потом использовать в своих целях и пользователю(оригинальному) не поможет ни смена пароля от аккаунта, ни выход из всех сессий(по факту она одна), ничего кроме удаления аккаунта вместе со всеми данными. Поэтому в куки обычно кладут длинную случайную последовательность символов, которая служит идентификатором сессии/токеном пользователя. А где-то в базе/редисе хранится связь этого токена с настоящим идентификатором пользователя в базе. При смене пароля от учетки пользователем, все его токены становятся не действительными

anonymous ()