Django中使用memcached

什么是memcached:

  1. memcached之前是danga的一个项目,最早是为LiveJournal服务的,当初设计师为了加速LiveJournal访问速度而开发的,后来被很多大型项目采用。官网是 www.danga.com 或者是 memcached.org。
  2. Memcached是一个高性能的分布式的内存对象缓存系统,全世界有不少公司采用这个缓存项目来构建大负载的网站,来分担数据库的压力。Memcached是通过在内存里维护一个统一的巨大的hash表,memcached能存储各种各样的数据,包括图像、视频、文件、以及数据库检索的结果等。简单的说就是将数据调用到内存中,然后从内存中读取,从而大大提高读取速度。
  3. 哪些情况下适合使用Memcached:存储验证码(图形验证码、短信验证码)、登录session等所有不是至关重要的数据。

安装和启动memcached

  1. windows下:
    参考链接:http://www.runoob.com/memcached/window-install-memcached.html

  2. linux下(ubuntu):

    • 安装:sudo apt install memcached
    • 启动:
sudo service memcached start

或者

sudo /usr/bin/memcached -d start

然后使用命令查看是否已经成功的启动了

sudo ps -aux | grep memcached
  1. 启动memcached的参数:
    • -d:这个参数是让memcached在后台运行。
    • -m:指定占用多少内存。以M为单位,默认为64M。
    • -p:指定占用的端口。默认端口是11211。
    • -l:别的机器可以通过哪个ip地址连接到我这台服务器。如果是通过service memcached start的方式,那么只能通过本机连接。如果想要让别的机器连接,就必须设置-l 0.0.0.0。
      如果想要使用以上参数来指定一些配置信息,那么不能使用service memcached start,而应该使用/usr/bin/memcached的方式来运行。比如/usr/bin/memcached -u memcache -m 1024 -p 11222 start。

使用service memcached start默认就使用了-d参数。并且使用service不能跟上面的参数,只能使用上面的第二种方法才能跟上面的参数。

例如:

  1. 指定后台运行:

首先需要杀死刚才运行的memcached。

 sudo killall memcached

然后再手动启动memcached

/usr/bin/memcached -d start
  1. 指定后台运行,并且设置最大内存为1024M:
    首先杀死刚才运行的memcached
sudo killall memcached

然后启动:

/usr/bin/memcached -d -m 1024 start
  1. 指定占用的端口:(默认是11211

我们可以先使用命令查看端口

sudo netstat -pl | grep memcached

然后修改默认占用的端口号

killall memcached
/usr/bin/memcached -d -p 11222 start
  1. 指定别的机器可以通过哪个ip地址连接到我这台服务器。
killall memcached
/usr/bin/memcached -l 0.0.0.0 -d start

使用telnet操作memcached

首先我们先将上面的进程杀死,然后重新启动memcached。

killall memcached
sudo service memcached start

然后使用telnet连接memcached

语法:telnet ip地址 [11211]

telnet 127.0.0.1 11211
1. 添加数据:
  • set:
    语法:
  set key flas(是否压缩,0代表否,1代表是) timeout(过期时间) value_length(值的最大长度)
  value

示例:

set username 0 120 7
zhiliao

我们可以使用get命令查看我们的数据是否添加进去了。

get username

注意: 获取数据要注意过期时间,像上面我们设置的过期时间为120秒,那么那么120秒之后肯定获取不到值的。

  • add:

语法:

add key flas(0) timeout value_length
value

示例:

 add username 0 60 7
 xiaotuo

set和add的区别:add是只负责添加数据,不会去修改数据。如果添加的数据的key已经存在了,则添加失败,如果添加的key不存在,则添加成功。而set不同,如果memcached中不存在相同的key,则进行添加,如果存在,则替换。

2. 获取数据:
  • 语法:
get key
  • 示例:
get username
3. 删除数据

语法:

delete key

示例:

delete username

注意: flush_all:删除memcached中的所有数据。

4. incr 对一个数进行加法操作.所以只能对应数字类型
set age 0 120 2
18

# 对age加2
incr age 2
5.decr 对一个数字进行减法操作.
set age 0 120 2
18

# 对age减2
decr age 2
6. stats: 查看memcached的状态
stats

stats中一些有意义的参数如下:

  • get_hists: get命令命中了多少次.(get命令得到值了,就叫命中了.)
  • get_misses: get命令空了几次.
  • curr_items:当前memcached中的键值对的个数.
  • total_connections: 从memcached开启到现在总共的连接数.
  • curr_connections:当前memcached的连接数.
  • memcached默认最大的连接数是1024.

使用python操作mamcached

安装【python-memcached】: pip install python-memcached

  1. python连接mamcached:
import memcache

# 首先要确保你的memcached已经启动了
# 连接memcached
# 设置debug = True 会将错误信息显示出来
mc = memcache.Client(['127.0.0.1:11211'],debug=True)
  1. 设置数据:
# 设置数据
#  设置   key       value    过期时间
mc.set('username','zhiliao',time=120)
# 一次性设置多个   必须传入一个字典类型
mc.set_multi({'email':'[email protected]','tel':'13555555555'},time=120)
  1. 获取数据:
# 获取数据
# 获取一个数据
username = mc.get('username')
# 获取多个数据   必须传入一个列表
dict = mc.get_multi(['username','email','tel'])
print(username,dict)
  1. 删除数据:
# 删除数据
mc.delete('username')
mc.delete_multi(['email','tel'])

# 再获取数据,测试删除是否成功
username = mc.get('username')
dict = mc.get_multi(['username','email','tel'])
print(username,dict)
  1. 使数据自增长,只能对应数字类型的数据:
# 设置age
mc.set('age',18,time=120)
# 获取age
age = mc.get('age')
print(age)
# age自增长1,因为我们没有设置参数,即默认增长1
mc.incr('age')
age = mc.get('age')
print(age)
# age自增长10,设置增长的大小
mc.incr('age',10)
age = mc.get('age')
print(age)
  1. 使数据自减少:
# 设置weight
mc.set('weight',120,time=120)
# 获取weight
weight = mc.get('weight')
print(weight)
# weight减1
mc.decr('weight')
weight = mc.get('weight')
print(weight)
# weight减10
mc.decr('weight',10)
weight = mc.get('weight')
print(weight)

上面我们只连接了本机的memcached,那么我们想连接别人的memcached,那么在连接的时候我们就需要传递一个连接的ip地址的列表。

mc = memcache.Client(['127.0.0.1:11211','xxx.xxx.x.xxx:xxxxx'],debug=True)

这样,我们就连接了两个memcached,一个本机的,一个别人的ip地址的。我们还想要连接更多的,就只需要在列表中添加ip地址就行了。
但是,因为我们连接了多个memcached,而我们有没有设置存储算法(就是规定哪些变量往哪个ip地址存),所以我们设置的memcached变量就会随机的存储在我们连接的memcached中,并且只会在一个中存储。

注意: 我们要想连接到别人的memcached,那么别人的memcached必须开启了的,而且还必须设置可连接的ip地址,像在局域网下就要设置-l参数为0.0.0.0。防火墙也要关闭。

memcached安全机制:

我们在使用memcached的时候,我们直接用ip地址和端口号就进行了连接,不用输入用户名和密码之类的东西,那么这样就存在很大的安全隐患。

那么,怎么来提高我们memcached的安全性呢。

  1. 最简单粗暴的方法就是:设置-l参数为127.0.0.1,即只能本机连接到memcached,别人怎样都连接不上的。
    但是这种情况如果项目小了,服务器和memcached在一台电脑上,那么我们可以这样设置,但是如果我网站做大了,这样做肯定就不可行了。
  2. 使用防火墙:从我们发送请求到服务器,中间还有一个防火墙的。我们可以在防火墙哪里设置开放的端口与关闭的端口。因为每一个程序都会占用一个端口号的,所以我们可以设置防火墙的开放端口和关闭端口,从而使我们的网站更安全。
Created with Raphaël 2.2.0 发送请求 防火墙 服务器

在linux下使用ufw可以很容易的控制防火墙的关闭和开放。

  ufw enable # 开启防火墙
  ufw disable # 关闭防火墙
  ufw default deny # 防火墙以禁止的方式打开,默认是关闭那些没有开启的端口
  ufw deny 端口号 # 关闭某个端口
  ufw allow 端口号 # 开启某个端口

我的系统是ubuntu16.04,那么需要在前面都加一个sudo
命令。其他的linux系统需要切换到root用户下才能使用。

例如我不想让别人能连接到我的memcached:

sudo ufw deny 11211

那么我就将11211端口关闭就行了,如果设置的是其他端口,那么就修改相应的端口就是了。但是防火前这个功能有点鸡肋,因为我们不想让别人能连接到我们的memcached,那么我么 就直接设置-l参数为127.0.0.1就行了。虽然防火墙的功能在这里显的鸡肋,但是我们还是需要了解防火墙的工作机制。

在Django中使用memcached:

首先我们需要在settings.py中配置好缓存,即在settings中添加一个字典:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211',
    }
}

如果需要连接多个memcached的话,我们只需要在LOCATION那个地方的值设置为一个列表就行了,里面存放我们连接的memcached的ip地址。

然后我们新建一个视图函数来使用memcached:

from django.http import  HttpResponse
# 使用cache来操作memcached
from django.core.cache import cache

# Create your views here.
def index(request):
    cache.set('username','zhiliao',12000)
    username = cache.get('username')
    print(username)
    return HttpResponse('index')

然后添加映射。运行代码。

为了测试我们添加是否成功,我们可以在终端连接memcached来get一下username。

talnet 127.0.0.1 11211
get username

执行命令之后我们会发现获取不到username,是因为我们不能这样操作吗?

起始并不是,只不过在我们设置值的时候,django给我们的key做了一些处理,所以username并不是存在memcached中的值,我们可以使用命令来查看一下在memcached中的key是什么。:

stats items

然后我们可以发现有number后面有一个数字1,就是代表有一个值。然后我们执行命令查看一下这个值的key

stats cachedump 1 0

然后就会将memcached中的所有值的key显示出来,因为我们现在只有一个值,所以只会显示一个key
在这里插入图片描述

可以看到我们在django中设置的key为username,但是在经过django的处理之后,存储到django中的可以已经变为:1:username了。

然后我们可以get一下:1:username,就能呢个获取我们设置的值了。

注意: 只是在终端中获取获取值需要使用:1:username,在django中我们还是可以通过username来获取值的,就像上面一样。

那么如果我们不想要Django对我们设置的可以进行一系列操作,而是使用我们自定义的操作,我们应该怎样做呢?

我们只需要在对memcached进行配置的时候在传入一个我们自定义的函数就行了,在settings中修改我们刚才的CACHES这个字典

def KEY_FUNCTION(key,key_prefix,version):
    # 自定义存储到memcached中的key
    # django:username
    return 'django:' + key

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211',
        'KEY_FUNCTION': KEY_FUNCTION,
    }
}

这样我们就自定义好了我们自己的存储规则了django:username。我们也可以直接return key,就是直接对我们在Django中设置的key进行存储。

注意:

  1. 函数的的参数必须为3个,否则会报错,虽然有两个参数没有用到,但是我们必须写入。最好名字也是这三个,不强求。尽量。
  2. 函数名可以随便改,但是也最好是这个函数名。
  3. default字典中的key一定是这些,不能改动。

因为我们定义的函数非常简单,那么我们也可以直接使用python中的lambda表达式
我们就可以将定义的函数去掉了,然后写入代码:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211',
        # 使用函数
        # 'KEY_FUNCTION': KEY_FUNCTION,
        # 使用lambda表达式
        'KEY_FUNCTION':lambda key,key_prefix,version:'django:' + key
    }
}

这样,我们就不用再去设置一个函数了。

总结:

  1. stats items : 查看memcached中所有的key
  2. stats cachedump [items_id] 0 :查看这个items_id下的所有的key。

至于其他的memcached的操作,这里就不演示了,相信大家也是知道该如何在Django中进行操作memcached了。

想深入学习django的可以看一下这个视频:超详细讲解Django打造大型企业官网

你可能感兴趣的:(django)