Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5096147
  • 博文数量: 921
  • 博客积分: 16037
  • 博客等级: 上将
  • 技术积分: 8469
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-05 02:08
文章分类

全部博文(921)

文章存档

2020年(1)

2019年(3)

2018年(3)

2017年(6)

2016年(47)

2015年(72)

2014年(25)

2013年(72)

2012年(125)

2011年(182)

2010年(42)

2009年(14)

2008年(85)

2007年(89)

2006年(155)

分类: Python/Ruby

2011-03-30 14:11:13

So just yesterday we posted a tutorial on how to use redis to. Soon after we published the documentation on the new redis hash type went online. Now hashes by themselves aren’t exactly relations but, more so an object field store. Extending the same concepts from our first article in namespace utilization and using hashes we can accomplish the same thing in a more formal fashion.

We will repeat the same exercise from the first article, creating a username password store, using hashes.

Basic hash overview

Without going into the technical details we can simplify the concept of redis’s as a way to store fields in a redis key. In Pythonic terms we can make a redis key into a basic Python .

[key] : {‘field’ -> ‘value’, ‘field’ -> ‘value’, ‘field’ -> ‘value’}

Basic hash usage

 

  1. >>> r.hset("user:adam", "fullname", "Adam Smith")
  2. 1
  3. >>> r.hset("user:adam", "password", "thisisapassword")
  4. 1
  5. >>> r.hkeys("user:adam")
  6. ['fullname', 'password']
  7. >>> r.hvals("user:adam")
  8. ['Adam Smith', 'thisisapassword']
  9. >>> r.hgetall("user:adam")
  10. {'fullname': 'Adam Smith', 'password': 'thisisapassword'}

We will break it down line by line here

  1. First we are going to make the redis key “user:adam” a hash and set the field “fullname” in that has to the value “Adam Smith” with the redis command hset (Hash Set)
  2. Then we’ll do the same thing for the field “password” and set that field in the hash to it’s appropriate value.
  3. With the hkeys command we can see all of the keys in the hash set on that redis key
  4. hvals returns all of the values in the redis key
  5. More useful, is the hgetall command. This will return a Python dictionary of all of the fields set in the key

As you can see, this is an excellent way to store information about an object without “faking” a relation like in our previous tutorial.

As I mentioned in the conclusion of the last article, if we want to change how we store information in redis all we should have to do is to change is change the inner workings of the functions add_user, authenticate_user, delete_user and the rest of our fictitious application should operate without any changes.

Creating a new user

 

  1. r = redis.Redis("localhost")

  2. from hashlib import md5



  3. def add_user(username, fullname, password):

  4.     if r.sadd("users", username):

  5.         #r.set("user:%s:fullname" % username, fullname)

  6.         #r.set("user:%s:password" % username, md5(password).hexdigest() )

  7.         r.hset("user:%s" % username, "fullname", fullname)

  8.         r.hset("user:%s" % username, "password", md5(password).hexdigest())

  9.         return True

  10.     else:

  11.         return False

I left the original code in the function commented out so we can see the differences in the two methods here. In our original method we used the name space of redis itself to store the reference. In the updated fashion we are using redis’s hash data type to store the related fields.

  1. >>> add_user("adam", "Adam Smith", "wealthofnations")
  2. True
  3. >>> add_user("adam", "Adam Smith", "wealthofnations")
  4. False

This function operates in the same fashion as our old version did but, is using a different data structure in the backend.

Logging a user in

Now we’ll refactor our old authentication code to work with the new backend.

 

  1. def authenticate_user(username, password):

  2.     #if username in r.smembers("users"):

  3.     if r.sismember("users", username"):

  4.         passhash = md5(password).hexdigest()

  5.         #if passhash == r.get("user:%s:password" % username):

  6.         if passhash == r.hget("user:%s" % username, "password

Just as in the add_user function, we just need to make a small change. Now instead of fetching the related redis key we simply fetch the field from the hash of “user:*username*”.

>>> authenticate_user("adam", "wealthofnations")

2 True
  1. >>> authenticate_user("adam", "wealthofnations")
  2. True
  3. >>> authenticate_user("adam", "bad_password")
  4. False
3 >>> authenticate_user("adam", "bad_password")
4 False

We can see the function again performs just like the old function but, it pulls the password from the hash object instead of the related key

Deleting a user

Deleting a user using the hash store is much easier than using the related key store, since everything is just stored in one key instead of being spread out across multiple keys.

 

  1. def delete_user(username):

  2.     #if username in r.smembers("users"):

  3.     if r.sismembers("users", username):

  4.         r.srem("users", username)

  5.         r.delete("user:%s" % username)

  6.         #r.delete("user:%s:fullname" % username)

  7.         #r.delete("user:%s:password" % username)

  8.         return True

  9.     else:

  10.         return False

Now instead of having to delete the 2 related keys, we just need to delete the one key storing the hash of all of the user data

文章来自:

阅读(1888) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~