Flask开发(二十八)Memcached缓存系统
本篇导读:
- Memcached的基本概念
- Memcached的安装
- Memcached的基本使用
- Memcached的安全机制
对于一些语如短信验证码等信息,一般我们没有必要写人数据库中保存,可以验证码等信息保存到Memcached缓存系统中,设置510分钟内有效。本章主要围绕Memcached的安装,基本使用和安全机制等知识点进行介绍,重点内容是Memcached的基本使用。
本节首先介绍Memcached的基本概念,理解这些概念是学习Memcached的基础。了解Memcached的概念后,再介绍Memcached的安装和配置。
Memcached的基本概念
Memcached缓存系线是目前使用最广泛的高性能分布式内存缓存系统,是一个自由的高性能分布式内存对象缓存系统,国内外众多大型互联网应用都选择 Memcached提高网站的访问性能,缓存系统一般可以将一些不需要实时更新但是又极其消耗数据库的数据写到内存中缓有起来,缓存时间可以控制,需要的时候直接从内存中读取出来即可。
那么,什么样的数据适合放到缓存中呢?
(1)不需要实时更新但是又极其消耗数据库的数据,比如商品销售排行榜游榜歌曲榜单等,这些数据基本上都是一天统计一次,用户不会关注其是否是实时更新的。
(2)需要实时更新,但是数据更新频率不高的数据。
(3)与报表相关的一些统计数据,生成一次比较花费资源。
注意:哪些数据不适合放到缓存中呢?一般来说涉及支付,更新数据等核心数据不应该放到缓存系统中。
Memcached的安装
想要在服务器上部署缓存系统,需要安装 Memcached。安装源主要有 Linux版本和Windows版本。 Memcached最开始是作为Linu应用程序被安装在服务器上来使用的,但自从开源之后它又被重新编译,因此有了 Windows下的安装包。Jellycan Northscale两个站点都提供了Windows的二进制可执行文件,下载地址如下:
32位系统 1.2.5版本 http: //code jellycan. comifile/memcached-1.2.5-win32-bin.zip
64位系统1.4.5版 http://downloads.northscale. com/memcached-1.4.5-amd64.zip。
在1.4.5版本之前, Memcached可以被安装成一个服务,但之后的版本中该功能不存在了。因此Memcached的安装版本可以分为两类,类是1.4.5之前的版本,另一类是1.4.5之后的版本。
Memcached >= 1.4.5 版本安装
1、解压下载的安装包到指定目录。
2、在 memcached1.4.5 版本之后,memcached 不能作为服务来运行,需要使用任务计划中来开启一个普通的进程,在 window 启动时设置 memcached自动执行。
我们使用管理员身份执行以下命令将 memcached 添加来任务计划表中:
schtasks /create /sc onstart /tn memcached /tr "'c:\memcached\memcached.exe' -m 512"
注意:你需要使用真实的路径替代 c:\memcached\memcached.exe。
注意:-m 512 意思是设置 memcached 最大的缓存配置为512M。
注意:我们可以通过使用 "c:\memcached\memcached.exe -h" 命令查看更多的参数配置。
3、如果需要删除 memcached 的任务计划可以执行以下命令:
schtasks /delete /tn memcached
Memcached的基本使用
要想在Flask中使用Memcached,还需要安装Python-Memcached模块。执行下面命令安装:
pip install python-memcached
安装成功以后就可以在Flask中使用Memcached了。下面介绍5中基本的memcached命令。
set和set_multi命令的使用
set命令将键值对(key-val)存储于缓存中,set命用于将值val(作value指数据值)保存在指定的键key中(这里键的名称为kye,键的值为val),如果键名key在缓存中没有,则创建该键名并保存键的值。如果键名key已经存在,则用当前值替换先前的值。
命令格式为:
set(key,val,time=0,min_compress_len=0,bytes,noreply=False)
- key:存储的键名(可理解为key- -value结构中的键key)
- val:存储的值(可理解为key-value结构中的值 value)
- time:用于设置超时,单位为秒,为0表示永久保存(服务器重启失效)
- min_compress_len:用于设置zlib压缩。
- noreply:服务器应答信息,该参数为 Flase,告知服务器不需要应答。
set_multi:一次设定多个键值对保存在缓存中。如果键名不存在,则创建生成,如果键名已经存在,则用当前的值替换先前的值。命令格式如下:
set_multi(mapping,time=0,key_prefix='',min_compress_len=0,noreply=False)
参数说明如下:
- mapping:设置多个键值对
- time:用于设置超时,单位为秒,为0表示永久保存(服务器重启失效)
- min_compress_len:用于设置zlib压缩。
- key_prefix:是key的前缀,完整的键名是key_prefix+key,一般设置为空
- noreply:服务器应答信息,该参数为 Flase,告知服务器不需要应答。
set和set_multi的实例代码如下:
from flask import Flask import memcache app = Flask(__name__) mc = memcache.Client(['127.0.0.1:11211'],debug=True)#可以连接多个服务器 mc.set('name','王勃') mc.set_multi({'key1':'李白','key2':'杜甫'}) @app.route('/') def hello_world(): return 'Hello World' if __name__ == '__main__': app.run()
get和get_multi的使用
get:获取一个键值对的值,命令格式如下:
get(key)
参数说明如下:
- key:键值对中的键名,键值对key-value中的key,用于存放或查找缓存值。
get_multi:命令获取多个键值对的值,可以非同步地同时取得多个键值,返回的数据对象为字典,其命令格式如下:
get_multi(keys,key_prefix='')
桉树说明如下:
- keys:键名,可以有多个,是键名列表,多个键名用应为逗号分割。
- key_prefix:是key的前缀,完整的键名是key_prefix+key,该值一般为空。
from flask import Flask import memcache app = Flask(__name__) mc = memcache.Client(['127.0.0.1:11211'],debug=True) mc.set('name','王勃') mc.set_multi({'key1':'李白','key2':'杜甫'}) @app.route('/') def hello_world(): r1=mc.get('name') r2=mc.get_multi(['key1','key2']) print(r1) print(r2) return 'he' if __name__ == '__main__': app.run()
运行结果如下:
add命令的使用
add命令为添加一条键值对命令,用于将值val储存在指定的键名为key的单元中,如果已经存在key,则重复执行add操作会出现异常。命令格式如下:
add(key,val,time=0,min_compress_len=0,noreply=False)
参数说明如下:
- key:存储的键名,用于查找缓存中的值
- val:存储的值(可理解为key-value结构中的值 value)
- time:用于设置超时,单位为秒。
- min_compress_len:用于设置zlib压缩。
- noreply:服务器应答信息,该参数为 Flase,告知服务器不需要应答。
from flask import Flask import memcache app = Flask(__name__) mc = memcache.Client(['127.0.0.1:11211'],debug=True) mc.add('username','王勃',time=120) username = mc.get('username') print(username) mc.add('username','lisi',time=120) print(username) @app.route('/') def hello_world(): return 'Hello World' if __name__ == '__main__': app.run()
运行结果:
从上面代码可以看出,第二次add同一个键,就会报错。
replace命令的使用
replace命令为修改某个键名为key的值,如果key不存在,则抛出异常。该命令实际为用当前值去替换先前键名为key的值,内部调用了set()方法。其命令格式为:
replace(key,val,time=0,min_compress_len=0,noreply=False)
参数说明请参阅add命令。
from flask import Flask import memcache app = Flask(__name__) mc = memcache.Client(['127.0.0.1:11211'],debug=True) mc.add('username','王勃',time=120) username = mc.get('username') print(username) mc.replace('username','李白',time=120) username = mc.get('username') print(username) @app.route('/') def hello_world(): return 'Hello World' if __name__ == '__main__': app.run()
输出结果为:
append和prepend命令的使用
append用于向已存在key的value后面追加数据。append命令的基本语法如下:
append(key,value,time=0,min_compress_len=0,noreply=False)
参数说明如下:
- key:键值对中的键名,键值key-value结构中的key用于查找缓存系统中键名为key的缓存值。
- value:键值对中的键值,键值对key-value中的值,即储存在缓存中的值。
- time:用于设置超时,单位为秒。
- min_compress_len:用于设置zlib压缩。
- noreply:服务器应答信息,该参数为 Flase,告知服务器不需要应答。
prepend命令用于向已存在key的value前面追加数据,其基本语法如下:
prepend(key,value,time=0,min_compress_len=0,noreply=False)
参数说明请参照append命令。
from flask import Flask import memcache app = Flask(__name__) mc = memcache.Client(['127.0.0.1:11211'],debug=True) mc.add('username','王勃',time=120) username = mc.get('username') print(username) mc.append('username','是初唐四杰之一',time=120) username = mc.get('username') print(username) mc.prepend('username','诗人') username = mc.get('username') print(username) @app.route('/') def hello_world(): return 'Hello World' if __name__ == '__main__': app.run()
输出结果如下:
delete和delete_multi命令的使用
delete:用于在Memcached中删除指定的一个键值对。delete命令的基本语法如下:
delete(key,time=None,noreply=False)
参数说明如下:
- key:键值对中的键名,键值key-value结构中的key用于查找缓存系统中键名为key的缓存值。
- time:用于设置超时,单位为秒。
- noreply:服务器应答信息,该参数为 Flase,告知服务器不需要应答。
delete_multi:在Memcached中删除指定的多个键值对。delete_multi命令的基本语法如下:
delete_multi(keys,time=None,key_prefix='',noreply=False)
参数说明如下:
- keys:键名,可以有多个,是键名列表,多个键名用应为逗号分割。
- key_prefix:是key的前缀,完整的键名是key_prefix+key,该值一般为空。
- time:用于设置超时,单位为秒。
- noreply:服务器应答信息,该参数为 Flase,告知服务器不需要应答。
from flask import Flask import memcache app = Flask(__name__) mc = memcache.Client(['127.0.0.1:11211'],debug=True) mc.add('username','王勃',time=120) mc.add('username2','李白',time=120) mc.add('username3','杜甫',time=120) user1 = mc.get('username') user2 = mc.get('username2') user3 = mc.get('username3') print(user1) print(user2) print(user3) mc.delete('username') user1 = mc.get('username') print(user1) mc.delete_multi(['username2','username3']) user2 = mc.get('username2') user3 = mc.get('username3') print(user2) print(user3) @app.route('/') def hello_world(): return 'Hello World' if __name__ == '__main__': app.run()
输出结果如下:
decr和incr命令的使用
decr:在Memcached中进行自减操作,将Memcached中的一个值减少N(N默认为1)。decr命令的基本语法如下:
decr(key,delta=1,noreply=False)
参数说明如下:
- key:键值对中的键名,键值key-value结构中的key用于查找缓存系统中键名为key的缓存值。
- delta:每次执行自动减1,默认为1,也可以设定每次减去的数。
- noreply:服务器应答信息,该参数为 Flase,告知服务器不需要应答。
incr:在Memcached中进行自增操作,将Memcached中的一个值增加N(N默认为1)。incr命令的基本语法如下:
incr(key,delta=1,noreply=False)
参数说明参照decr。
from flask import Flask import memcache app = Flask(__name__) mc = memcache.Client(['127.0.0.1:11211'],debug=True) mc.add('num',99,time=120) num = mc.get('num') print(num) mc.decr('num',delta=5) num = mc.get('num') print(num) mc.incr('num',delta=10) num = mc.get('num') print(num) @app.route('/') def hello_world(): return 'Hello World' if __name__ == '__main__': app.run()
运行效果如下:
Memcached的安全机制
访问 MySQL等数据库服务器时,一般要求用户在配置文件中配置用户名、密码、指定数据库的名称等,用户必须设置正确才能对数据库进行各种访问操作,安全性还是比较高的。而使用 Memcached服务,没有要求用户输入用户名和密码这样的安全机制,程序是直接通过客户端工具 Telnet等连接操作,存在比较大的安全隐患。如何减少安全隐患、降低数据泄漏,以及服务器被入侵的风险,是我们使用 Memcached服务必须要考虑的问题。从实际出发,使用 Memcached服务,提升其安全机制的方法主要有两种方法。一种方法是设置内网访问。此种情况下,数据库服务器和 Memcached服务器可以是同一台服务器,Web服务器是独立的一台服务器。Web服务器对缓存数据进行存取的时候,,只能通过局域网方式下的IP来访问,,Memcache的服务器监听内网的IP地址和开放的相应的端口。只要是外网IP,一律视非非法访问。另一种方法是设置防火墙,防火墙可以考虑硬件防火墙和软件防火墙综合使用。在防火墙设置中,只开放相应的IP和端口号,对于没有开放的IP段和端口号一律过滤掉,确保只有自己的Web服务器能够访问到对应的数据库服务器和 Memcached服务器。关于防火墙设置等知识,请参阅防火墙设置等相关资料。