Trying to have a user database in redis, how is it possible to implement a logic so that each and every user has unique emails and unique usernames?
{
id int64 autoincremented
email string UNIQUE
username string UNIQUE
hashedPassword string
token string
.
.
}
Redis does not support constraints. However, you can manage usernames and email uniqueness on client side.
For example, you can maintain on redis a sorted set that contains all existing usernames in redis and an another sorted set that contains all emails in redis.
Before the client insert the user in redis, it query both sets with ZSCORE command if ZSCORE return NULL, the element not exists in the sorted set and also in database. If both ZSCORE commands reply with NULL, the client can insert the new client and insert username and emails in both sorted sets.
Related
We are building a multi-tenant application that supports multiple clients. Let's use an accounting application as an example - each organization has its own accounts, receipts, etc (with their own unique id). In our case, the numbers of clients is small.
There are two options to go about it
Unique ids (UUIDs) are created by our app, and the client is responsible for maintaining a mapping of their own ids, to our UUIDs. This is easier to support but adds complexity to the client (need to maintain an extra UUID, and potentially have to pass it between their own micro-services)
We let the client specify the ids of the object in the API call as if they are the only tenant, and somehow handle the uniqueness in the background.
If we go with the 2nd approach, then we need to combine the clientId with the objectId. We could think of 3 ways to do it
A DB table per client. We decide which table to use based on the client_id. Requires either manually, or automatically creating a full set of tables per client.
DB composite keys.(I am aware of the performance hit of using Strings as pkeys, )
CREATE TABLE User (
clientId String,
userId String,
PRIMARY KEY (clientId, userId)
)
Application level: Application maintains both, and is responsible for returning the client their id, while producing the internal UUID for internal use. The internal id can be optimized for storage type. For example (Scala)
trait UniqueId[T]{
val toClientId: String // The unique id we got from a client
val to InteralId: T // The unique id we use internally
}
case class Id(client: Client, userId: String) extends UniqueId[...]{
val toClientId = userId
// Could have any of...
val to InteralId = s"${client.name}_${userId}"
val to InteralId = MD5(s"${client.name}_${userId}")
}
I do not see any question here, but I supposed you want some advice on the way to go ;-)
If you have a database that is multitenant aware (oracle multitenant, or a db with partition) you could easily implement your solution 1.
I would personnaly use an internal guid or int surrogate to identify each objects and would store the client ID only once as an attribute...
What is the best table design for a simple social networking website using Azure Table Service?
The website could have millions of users.
Users need to be able to view a list of all other users in the system sorted by the number of mutual connections.
Users must be able to view a list of their connections
User must be able to view content posted by themselves and their connections.
One major design constraint is that Azure table service queries are generally limited to the partition key and row key when there are a large number of records or else they get really slow. Another constraint is that query results are only sorted by the partition key and then the row key.
Try this Design:
UserTable
PK: GUID ( GUID for PK will maximize scalability, only one partition with single row in each server)
RK: GUID
... Rest of properties
UserFriendsTable
PK: UserTable.RK ( Every User with his friends in a separate server)
RK: GUID
FriendWith: UserTable.Pk - UserTable.RK (Concatenate PK and RK from user table separated with "-", this will help you to execute point query fast when you try to access friend profile )
PostsTable
PK: UserTable.RK + "-" +YYYYMM+ Random number (This will allow azure to put all monthly posts of any user in a separate server. Random number to prevent azure from auto grouping partitions in sequence. You can query posts with filtering PK partly ex: pk start with XCtghi94ktY-201411.
RK use following code to generate row key in descending order. means latest post comes first.
long ticks = DateTimeOffset.MaxValue.UtcDateTime.Ticks - DateTimeOffset.Now.UtcDateTime.Ticks;
string guid = Guid.NewGuid().ToString("N");
string suffix = "-";
string.Format("{0:d21}{1}{2}", ticks, suffix, guid);
Post : String
I use redis to store user sessions by a guid i generate when the log in. I use that as the key in their session object.
If i was to lock a user's account I currently have to go through all sessions and check if they are the user's then delete them.
Is there a way to also query by the user id? Should I be using the sorted set insured of just standard key value?
Going through all keys is probably not the best idea. What you could do is store every user sessions' guids in another key - the set data type seems to be the best choice for that - and add/remove from it as the user opens/closes a session. So, when a user opens a new session you will:
SET session:<guid> <session_object>
SADD user_sessions:<user_id> <session_guid>
and when the session is closed, you'll do:
DEL session:<guid>
SREM user_sessions:<user_id> <session_guid>
To find which session guids are a user's, e.g. for an account lock down, do:
SMEMBERS sessions:<user_id>
In my PostgreSQL database I have table users which has two columns, PK named uid(serial) and user_type(integer). Is it possible that for regular users (of user_type 1) uid starts from 0 (and increments regularly), and for non-regular users (of user_type 2), uid starts from (let's say) 5000, and to increments from that number (5000, 5001, 5002...) each time new non-regular user is added?
I won't have more than 2000 regular users, so overlap between uids of regular and non-regular users will never happen.
A serial data type will create a sequence and pull the default value for your column out of that sequence. For what you're trying to do you'd need two sequences, pull from these sequences and insert the uid explicitly. This is not something the serial can nor should do.
To echo #a_horse_with_no_name, you shouldn't put information into a serial data type. A generated primary key is only acceptable if it is completely opaque to the table users. Please consider just letting serial do its work and update your application code to react properly to user_type. Since your concern seems to be id collision with external entities, I'd suggest storing the user ids generated by an external system in a separate field, say extern_uid.
Or have the external system generate UUID strings you can safely use in your uid column. If the external system is a PostgresSQL database as well, you might use the uuid-ossp module to generate the UUID/GUID.
If you absolutely have to use sequences, you'd need to:
CREATE SEQUENCE uid_one START 1;
CREATE SEQUENCE uid_two START 5000;
INSERT INTO user (uid, user_type) VALUES (nextval('uid_one'::regclass), 1);
INSERT INTO user (uid, user_type) VALUES (nextval('uid_two'::regclass), 2);
Selecting the appropiate statement is left to the application.
Im making an app where I have a server-side sql database to store the user settings of all users.
Im not sure how to make each user unique, so that the database knows who is who.
The database is storing these user data for each row: id, email, county, age and gender.
So im thinking the best way is to make the user unique to he/she's email - which is unique - so that the when the settings are updated or outputted, the sql knows what row to fetch.
How should I go about with this?
And how would i then output the right data to the right user?
An entity in the database should have a primary key. I understand that in your design the id field is going to be the primary key. Usually this is an auto-generated integer. This is called a surrogate key In this case you need to tell to the table that the email field must be unique as well. You can do that by creating a unique index for this field. The unique index will prevent the creation of two different users with the same email. Going with this approach you can query the table checking either for id or for email.
An alternative is to have natural key. In this case, email would be the primary key of your table, so you wouldn't have the id field. Going with this approach you can query the table checking either for email, which is the unique identifier of each user.