Redis : REmote DIctionary Server / Redistribute
Redis is an in-memory data structure store, used as a database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs and geospatial indexes with radius queries.
In-memory $\Rightarrow$ très rapide
Redis = data-structure store
Observation : the bigger the storage is, the slower it will be.
A cache is a component that stores recently accessed data in a faster storage system. Each time a request for that data is made, it can (with some probability) be pulled from the faster memory.
Application permettant de publier et lire des livres en ligne. MongoDB ou SQLite (ou autre...) peut être utilisé pour la base principale, l'idée étant d'accéder plus rapidement aux livres consultés souvent : on utilise Redis pour ça.
If you plan to use Redis just as a cache where every key will have an expire set, you may consider using the following configuration
maxmemory 2mb maxmemory-policy allkeys-lru
In this configuration all the keys will be evicted using an approximated LRU algorithm as long as we hit the 2 megabyte memory limit.
Voir par ici pour quelques algorithmes de remplacement de cache.
$\Rightarrow$ Redis PUB/SUB
Avantage : les messages peuvent être lus par n'importe quelle application dialoguant avec le server Redis
Fichier "settings.py"
# pip install redis ...
import redis
config = {
'host': 'localhost',
'port': 6379,
'db': 0,
}
r = redis.StrictRedis(**config)
Fichier "pub.py"
from settings import r
import sys
if __name__ == '__main__':
name = sys.argv[1]
channel = sys.argv[2]
print('Welcome to ' + channel)
while True:
print('Enter a message:')
message = sys.stdin.readline()
if message.lower() == 'exit':
break
message = name + ' says: ' + message;
r.publish(channel, message)
Fichier "sub.py"
from settings import r
import sys
if __name__ == '__main__':
channel = sys.argv[1]
pubsub = r.pubsub()
pubsub.subscribe(channel)
print('Listening to ' + channel)
while True:
for item in pubsub.listen():
print(item['data'])
Ne reste plus qu'à taper (démo ?)
python sub.py PYTHON
dans un terminal (serveur), et
python pub.py Ben PYTHON
dans un autre (client).
"We are already using MongoDB to store our records, can't we just put everything in one place?"
MongoDB is a good tool. We like to think of it as the Hammer of Databases: a general purpose Datastore that works well for most NoSQL situations. But if you need to save/access Millions of Records Per Second then there's only one place to store your data: Redis.
Différences entre les deux.
var indexedDB = window.indexedDB
// Open (or create) the database
var open = indexedDB.open("MyDatabase", 1);
// Create the schema
open.onupgradeneeded = function() {
var db = open.result;
var store = db.createObjectStore("MyObjectStore",
{keyPath: "id"});
var index = store.createIndex("NameIndex",
["name.last", "name.first"]);
};
open.onsuccess = function() {
// Start a new transaction
var db = open.result;
var tx = db.transaction("MyObjectStore", "readwrite");
var store = tx.objectStore("MyObjectStore");
var index = store.index("NameIndex");
// Add some data
store.put({id: 12345,
name: {first: "John", last: "Doe"}, age: 42});
store.put({id: 67890,
name: {first: "Bob", last: "Smith"}, age: 35});
// Query the data
var getJohn = store.get(12345);
var getBob = index.get(["Smith", "Bob"]);
getJohn.onsuccess = function() { // => "John"
console.log(getJohn.result.name.first); }
getBob.onsuccess = function() { // => "Bob"
console.log(getBob.result.name.first); }
// Close the db when the transaction is done
tx.oncomplete = function() { db.close(); }; }
IndexedDB API :
assez complexe à utiliser directement,
les requêtes ne se font pas très naturellement.
Choix pour ce cours : Dexie.js
var db = new Dexie("todos-dexie");
db.version(1).stores({ todo: '_id' })
db.open()
.then(refreshView);
function onClick(e) { //clic sur une tâche
db.todo
.where('_id').equals(e.target.getAttribute('id'))
.delete()
.then(refreshView); }
function onSubmit(e) { //nouvelle tâche
db.todo.put({ text: input.value, _id: String(Date.now()) })
.then(function() { input.value = ''; })
.then(refreshView); }
function refreshView() {
return db.todo.toArray()
.then(renderAllTodos); }
function renderAllTodos(todos) { /* ... */ } //...
Pas encore écrite... mais nécessite au moins les tables :
Puis éventuellement des tables "équipes", "arbitres" ...
db.version(1).stores({
players: 'name',
matchs: '++id' });
db.players.put({name: "Nicolas", license: "1234ABCD"})
.then (function() { ... }) //...
Lister les clubs par taille décroissante
db.players.get('project on club only?').distinct()
.then( function(allClubs) { //...
allClubs.forEach( c => {
db.players.where(club).equals(c).count() //...
Obtenir les nombres de points par joueur
// Par exemple pour name = "Alice"
db.matchs.where("joueurs").includes("Alice")
.where('Elle a gagné...').count()
$\rightarrow$ Requêtes à adapter...
Dans le navigateur aussi ! (compilé en js via Emscripten)
var sql = require('sql.js'); //or sql = window.SQL
var db = new sql.Database(); //or new sql.Database(data)
sqlstr = "CREATE TABLE hello (a int, b char);";
sqlstr += "INSERT INTO hello VALUES (0, 'hello');"
sqlstr += "INSERT INTO hello VALUES (1, 'world');"
db.run(sqlstr); // Run the query without returning anything
var res = db.exec("SELECT * FROM hello");
// [ {columns:['a','b'], values:[[0,'hello'],[1,'world']]} ]
// Prepare an sql statement
var stmt = db.prepare(
"SELECT * FROM hello WHERE a=:aval AND b=:bval");
// Bind values to the parameters and fetch the results
var result = stmt.getAsObject(
{':aval': 1, ':bval': 'world'});
console.log(result); // Will print {a:1, b:'world'}
Bases dans le navigateur utiles
Exemple : un jeu vidéo, dont les données sont sauvegardées localement en mode offline puis synchronisées avec le serveur au retour de la connection (on peut imaginer un jeu d'aventure type Zelda 2D où une partie de la carte est chargée localement).
Sujets abordés
Sujets non abordés (cf. suite de cursus ?)