您的位置:首页 > 数据库 > Memcache

Redis, Memcache 基本使用

2017-12-21 11:17 330 查看

Redis, Memcache

Memcache

MemCache是一个自由、源码开放、高性能、分布式的内存对象缓存系统,用于动态Web应用以减轻数据库的负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高了网站访问的速度。

安装

https://github.com/memcached/memcached/wiki/Install

启动服务

memcached -d -m 10    -u root -l 10.211.55.4 -p 12000 -c 256 -P /tmp/memcached.pid

参数说明:
-d 是启动一个守护进程
-m 是分配给Memcache使用的内存数量,单位是MB
-u 是运行Memcache的用户
-l 是监听的服务器IP地址
-p 是设置Memcache监听的端口,最好是1024以上的端口
-c 选项是最大运行的并发连接数,默认是1024,按照你服务器的负载量来设定
-P 是设置保存Memcache的pid文件


测试时可以关闭防火墙,否则客户端无法访问:
systemctl stop firewalld.service


python中操作MemCache

安装API

pip install python-memcached -i https://pypi.douban.com/simple[/code] 

操作测试

这里在Django项目中测试

from django.conf.urls import url
from django.shortcuts import HttpResponse
import memcache

def test(request):
mc = memcache.Client(['192.168.14.16:12000'], debug=True)
mc.set('name', 'Lena', time=5)  # 超时5秒
name = mc.get('name')
return HttpResponse(name)

urlpatterns = [
url(r'^test/', test),
]


分布式缓存

配置多个服务端,并设置权重,权重越高,命中几率越高。

mc = memcache.Client([('192.168.14.16:12000', 1), ('192.168.14.17:12000', 2), ('192.168.14.18:12000', 3)], debug=True)  # 分别设置1,2,3权重


Memcache的分布式是由客户端程序的一致性哈希实现的,更多参考:http://www.csdn.net/article/2016-03-16/2826609

MemCache常用方法

注意:

MemCache中存的值只支持字符串和数字

超时设置的时间单位是秒,超时后取出结果是
None


命 令作 用
get返回Key对应的Value值:mc.get(key)
add添加一个Key值,没有则添加,有则报错:
mc.add(key, val, time=10)
添加键值,并设置超时10秒
set设置一个Key值,没有就增加,有就覆盖:
mc.set(key, val, time=10)
replace按照相应的Key值替换数据,如果Key值不存在则会操作失败:
mc.replace(key, val)
delete删除一个键值对:
mc.delete(key)
stats返回MemCache通用统计信息
flush_all清空所有键值,但不会删除items,所以此时MemCache依旧占用内存:
mc.flush_all()

其它方法

set_multi 设置多个键值对

mc.set_multi({k1: v1, k2: v2})


del_multi删除多个键值对

mc.set_multi([k1, k2])


incr & decr

将key对应的值增加/减小

mc.set('a', 10)
mc.incr('a', 10)  # 'a' = 20
mc.decr('a', 5)  # 'a' = 15


append & prepend

在指定key值后面/前面追加

mc.set('name', 'Lena')  # 'name'= 'Lena'
mc.append('name', 'Ayhan')  # 'name' = 'LenaAyhan'


cas & gets

为了避免两个请求同时修改某个值,造成数据异常。
gets
cas
需要配合使用。

通过
gets
获取值的时候(假设是val),会多返回一个数字,就叫做cas_id吧,当val改变时(比如期间有另一个请求修改了val),这个cas_id也会变。当执行
cas
(check and set)重新设置值时,将检查cas_id是否和gets取出值时的cas_id匹配,如果匹配则修改,如果不匹配,表示期间有其它请求修改了val,则无法修改.

val = mc.gets(key)
# ...
# 如果在gets和cas之间有请求修改了key的值,那么,下面的cas将会检查到cas_id变了,抛出异常,避免修改造成数据异常
mc.cas(key, new_val)


Redis

同MemCache一样,Redis也是在服务器内存中保存的非关系型数据库(缓存),但是二者还是有些区别:

如果你对数据持久化和数据同步有所要求,那么推荐你选择Redis,因为这两个特性Memcached都不具备。即使你只是希望在升级或者重启系统后缓存数据不会丢失,选择Redis也是明智的。

Redis相比Memcached来说,拥有更多的数据结构和并支持更丰富的数据操作。

Redis不仅可以支持分布式,还具有高可用的特点:可以将数据定时刷入硬盘,解决了内存断电易失的问题。并且它支持更多的的数据类型:字符串,数字,列表,集合,字典,有序集合。

在python中使用Redis

centos服务端安装

yum install redis

4000

如果安装不上,先安装epel仓库
yum install epel-release
,再执行上述安装命令。

启动服务端:

systemctl start redis


配置:

vim/etc/redis.conf

# bind 127.0.0.1  这一行要注释掉,否则客户端连接不上
equirepass 123  # 设置密码


客户端安装:

pip install redis


连接

方式一

import redis
conn = redis.Redis(host=, port=, password='123')


不推荐,每次都会重新连接,创建新的对象。

方式二 推荐

推荐用连接池:

pool = redis.ConnectionPool(host=xx, port=xx, password='123')
conn = redis.Redis(connection_pool = pool)


进阶:单例模式

这里的host, port, password可以写到配置文件中。

import redis

class Singleton(object):
def __new__(cls, *args, **kwargs):
# 如果当前类没有_instance属性,那么就调用父类的__new__方法实例化对象,新增_instance属性并赋值
if not hasattr(cls, "_instance"):
cls._instance = super(Singleton, cls).__new__(cls)
return cls._instance

class SingleRedis(Singleton):
def __init__(self, host='192.168.14.16', port=6379, password=123):
pool = redis.ConnectionPool(host=host, port=port, password=password)
self.conn = redis.Redis(connection_pool=pool)

# 使用
redis = SingleRedis()
redis.conn.set(key, val)


字符常用操作

conn.set(name, value, ex=None, px=None, nx=False, xx=False)

为name设置value(字符/数字类型);

ex/px
: 过期时间(秒/毫秒);

nx
: 如果为True,那么只有当name对应的value不存在时,该操作才能成功(即如果name在Redis中已经有value,将不会设置新的value,保留原来的值);默认False,无论如何设置新值。

xx
: 如果为True,那么只有当name对应的value已经存在时,该操作才能成功(即只能更新已存在的name)。

conn.mset(*args, **kwargs)

批量设置值

conn.mset(k1=v1, k2=v2)
# 或者
conn.mset({k1: v1, k2: v2})


conn.get(name)

返回name对应的value,如果不存在返回None

conn.get(keys, *args)

批量获取值

conn.mget(k1, k2)
# 或者
conn.mget([k1, k2])


conn.incr/decr(name, amount=1)

将name对应的value增加/减少amount,如果name不存在,将创建并初始化值为amount

列表常用操作

conn.lpush(name, *values)

往name对应的列表中添加元素(依次添加到最左边)

redis.conn.lpush('fruits', 'banana', 'orange')
# fruits: ['orange', 'banana']


conn.rpush(name, *values)

往k对应的列表中添加元素(从右边添加)

conn.llen(name)

name对应列表的长度

conn.lpop(name)

name对应列表的左边弹出一个值并返回

conn.rpop(name)

name对应列表的右边弹出一个值并返回

字典常用操作

conn.hset(name, key, value)

设置字典 name: {key: value};

conn.hset(name, key2, value2)
name: {key: value, key2: value2} 字典

注意如果value是字典或其它格式,需要先序列化为字符串

conn.hget(name, key)

获取name对应字典中key对应的value

conn.hdel(name, key)

删除name对应字典中的key

集合操作

将前缀s改为z,即可变为有序集合

conn.sadd(name, *values)

往name集合中添加元素

conn.scard(name)

返回name集合中元素的个数

conn.smembers(name)

获取name集合中的所有元素

conn.srem(name, *values)

删除name集合中某些元素

其它操作

delete(*names)

删除指定的keys

exists(name)

判断name是否存在,返回True/False

expire(name, time)

为某个name设置超时时间,单位是秒
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息