使用Python集合类型实现ACL
目前我有一些表,比如:Pages, Groups, GroupPage, Users, UserGroup
。通过使用“腌制集合”(pickled sets),我可以只用3个表来实现相同的功能:Pages, Groups, Users
。
set
(集合)似乎是实现访问控制列表(ACL)的自然选择,因为与组和权限相关的操作可以很自然地用集合来表示。如果我把允许和拒绝的列表存储为“腌制集合”,那么就可以减少一些中间表,从而简化多对多关系,并且可以在不进行很多数据库操作的情况下编辑权限。
如果需要人类可读性,我可以选择用json代替cPickle进行序列化,并在Python中使用set
来处理权限列表。直接用SQL编辑权限的可能性非常小。所以,这样的设计思路好吗?
我们使用SQLAlchemy作为对象关系映射(ORM),所以很可能会用到PickleType
这一列。我并不打算存储整个“资源”记录集,只会存储由“资源”主键值构成的set
对象。
4 个回答
我会选择把持久的信息存放在关系型数据库里,使用一种和具体编程语言无关的格式。虽然我非常喜欢Python(而且是非常非常喜欢),但总有一天我可能会想用其他语言来访问这些信息。如果我用Python特有的格式来存储数据,那我可就真后悔了……
你需要考虑数据库管理系统(DBMS)能给你提供什么功能,以及你需要重新实现哪些功能。并发性问题是一个很大的挑战。有几个竞争条件需要注意,比如多个线程和进程同时写入数据,可能会导致新数据被覆盖;还有性能问题(写入策略是什么?如果你的程序崩溃了,数据会丢失吗?);以及内存问题(你的权限设置有多大?这些能全部放进内存里吗?)。
如果你有足够的内存,并且不需要担心并发问题,那么你的解决方案可能是可行的。否则,我建议你还是使用数据库,因为它们可以帮你解决这些问题,而且为了确保数据始终从一个一致的状态转到另一个状态,数据库系统已经投入了大量的工作。
如果你打算把集合(sets)存储起来,最好找一个合适的对象数据库,比如 ZODB。在纯关系型数据库的环境中,你的集合会被存储为BLOB(大二进制对象),这样处理起来还不错。但是在使用ORM(对象关系映射)的时候,尝试存储集合可能会导致一些让人困惑的问题,因为ORM通常假设数据是纯关系型的,而不是需要解码的BLOB。
集合和其他一类对象其实更适合放在数据库里。ORM算是一种变通的做法,因为有些人认为关系型数据库“更好”,所以我们就加了一个映射层。
如果使用对象数据库,你会发现事情通常会顺利得多。
编辑
SQLAlchemy有自己的序列化工具。
http://www.sqlalchemy.org/docs/05/reference/ext/serializer.html
这既不是pickle也不是cPickle。不过,因为它需要可扩展,所以它的行为会像pickle。对于你的需求来说,这样的速度是足够的。你不会一直在反序列化ACL(访问控制列表)。