memcache

memcache简介

Memcached是一个自由开源的,高性能,分布式内存对象缓存系统。

Memcached是以LiveJournal旗下Danga Interactive公司的Brad Fitzpatric为首开发的一款软件。现在已成为mixi、hatena、Facebook、Vox、LiveJournal等众多服务中提高Web应用扩展性的重要因素。

Memcached是一种基于内存的key-value存储,用来存储小块的任意数据(字符串、对象)。这些数据可以是数据库调用、API调用或者是页面渲染的结果。

Memcached简洁而强大。它的简洁设计便于快速开发,减轻开发难度,解决了大数据量缓存的很多问题。它的API兼容大部分流行的开发语言。

本质上,它是一个简洁的key-value存储系统。通过socket连接和发送命令

一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、提高可扩展性。

特征

协议简单

基于libevent的事件处理

内置内存存储方式

memcached不互相通信的分布式

memcached安装

参考安装链接地址:http://www.runoob.com/memcached/window-install-memcached.html

当前安装方法:

[root@centos6 ~]# yum install memcached -y
[root@centos6 ~]# memcached -d -m 10 -u root -l 172.1.1.7 -p 11211 –P /tmp/memcached.pid #启动

参数说明:

-d 是启动一个守护进程

-m 是分配给Memcache使用的内存数量,单位是MB

-u 是运行Memcache的用户

-l 是监听的服务器IP地址

-p 是设置Memcache监听的端口,最好是1024以上的端口

-c 选项是最大运行的并发连接数,默认是1024,按照你服务器的负载量来设定

-P 是设置保存Memcache的pid文件

python操作memcached:

  • 安装API:
python操作Memcached使用Python-memcached模块

下载安装:https://pypi.python.org/pypi/python-memcached
  • python操作memcached
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import memcache
memc=memcache.Client(['172.1.1.7:11211'],debug=True) #连接远程mencache
memc.set('key1','value1') #写入键值对
rec=memc.get('key1') #按照key读取参数
print(rec)
  • 连接memcached集群

memc=memcache.Client([(‘172.1.1.6:11211’,1),(‘172.1.1.2:11211’,2)],debug=True)

权重的计算:

python-memcached模块原生支持集群操作,其原理是在内存维护一个主机列表,且集群中主机的权重值和主机在列表中重复出现的次数成正比;

如果用户根据如果要在内存中创建一个键值对(如:k1 = "v1"),那么要执行一下步骤:

  1. 根据算法将 k1 转换成一个数字
  2. 将数字和主机列表长度求余数,得到一个值 N( 0 <= N < 列表长度 )
  3. 在主机列表中根据 第2步得到的值为索引获取主机,例如:host_list[N]
  4. 连接 将第3步中获取的主机,将 k1 = "v1" 放置在该服务器的内存中
  • add操作
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import memcache
#添加一条键值对,如果已经存在的 key,重复执行add操作异常
memc = memcache.Client(['172.1.1.7:11211'],debug=True) #连接memcache服务端
memc.add('k1','v1') #添加参数
# memc.add('k1','v2')
  • replace操作
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import memcache
#replace 修改某个key的值,如果key不存在,则异常
memc=memcache.Client(['172.1.1.7:11211'],debug=True)
memc.replace('k1','vvvv')
kk=memc.get('k1')
print(kk)
  • set&set_multi

    • set 设置一个键值对,如果key不存在,则创建,
    • 如果key存在,可以修改 set_multi 设置多个键值对,如果key不存在,则创建,如果key存在,可以修改
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import memcache
memc=memcache.Client(['172.1.1.7:11211'],debug=True)
#memc.set('s1','t1')
memc.set_multi({'s2':'k2','s3':'k3'}) #千万要记住此处是引号
  • delete&delete_multi

    • delete 在Memcached中删除指定的一个键值对
    • delete_multi 在Memcached中删除指定的多个键值对
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import memcache
memc = memcache.Client(['172.1.1.7:11211'],debug=True)
#memc.delete('s1')
memc.delete_multi(['s2','s3'])
  • get&get_multi

    • get            获取一个键值对
    • get_multi   获取多个或者一个键值对
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import memcache
memc=memcache.Client(['172.1.1.7:11211'],debug=True)
val1 = memc.get('s1') #取的值不存在就为None
print(val1)
val2 = memc.get_multi(['s1','s2','s3'])
print(val2)
  • append&prepend

    • append    修改指定key的值,在该值 后面 追加内容
      prepend   修改指定key的值,在该值 前面
      插入内容
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import memcache
memc = memcache.Client(['172.1.1.7:11211'],debug=True)
memc.append('s7','after')
memc.prepend('s7','before')
t=memc.get('s7')
print(t)

decr&incr

  • incr  自增,将Memcached中的某一个值增加 N ( N默认为1 )
    decr 自减,将Memcached中的某一个值减少 N (
    N默认为1 )
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import memcache
memc=memcache.Client(['172.1.1.7:11211'],debug=True)
memc.set('k1','789')
t1=memc.incr('k1')
print(t1)
t2=memc.decr('k1')
print(t2)
  • gets&cas(最重要的)

    如商城商品剩余个数,假设改值保存在memcache中,product_count = 900
    A用户刷新页面从memcache中读取到product_count =
    900
    B用户刷新页面从memcache中读取到product_count = 900

    如果A、B用户均购买商品

    A用户修改商品剩余个数 product_count=899
    B用户修改商品剩余个数 product_count=899

    如此一来缓存内的数据便不在正确,两个用户购买商品后,商品剩余还是
    899
    如果使用python的set和get来操作以上过程,那么程序就会如上述所示情况!

    如果想要避免此情况的发生,只要使用 gets 和 cas 即可,如:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import memcache
    memc=memcache.Client(['172.1.1.7:11211'],debug=True)
    v=memc.gets('product_count')
    memc.cas('product_count','211') #再次修改则会出错
    print(v)
    memc.cas('product_count','122') #设定值

本质上每次执行gets时,会从memcache中获取一个自增的数字,通过cas去修改gets的值时,会携带之前获取的自增值和memcache中的自增值进行比较,如果相等,则可以提交,如果不想等,那表示在gets和cas执行之间,又有其他人执行了gets(获取了缓冲的指定值), 如此一来有可能出现非正常数据,则不允许修改。

redis

  • 简介:

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

  • redis的安装
[root@centos6 opt]# tar xf redis-3.0.3.tar.gz
[root@centos6 opt]# mv redis-3.0.3 redis
[root@centos6 opt]# cd redis
[root@centos6 redis]# make && make install
[root@centos6 redis]# /opt/redis/src/redis-server /opt/redis/redis.conf &     #启动服务
  • 客户端操作
[root@centos6 ~]# /opt/redis/src/redis-cli      #客户端连接
127.0.0.1:6379> set 'foo' 'bar' #设定键值对
OK
127.0.0.1:6379> get 'foo' #按照key取出值
"bar"
  • python操作redis

    redis-py 的API的使用可以分类为:

      • 连接方式
      • 连接池
      • 操作
        • String 操作
        • Hash 操作
        • List 操作
        • Set 操作
        • Sort Set 操作
      • 管道
      • 发布订阅

连接方式

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red=redis.Redis(host='172.1.1.7',port=6379) #创建连接
red.set('foo','bar') #存入键值对
print(red.get('foo')) #按照key取出值

连接池

redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red=redis.ConnectionPool(host='172.1.1.7',port=6379) #创建连接池
poo=redis.Redis(connection_pool=red) #创建连接
poo.set('hello','nimei')
print(poo.get('hello'))

操作

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

在Redis中设置值,默认,不存在则创建,存在则修改

参数:

ex,过期时间(秒)

px,过期时间(毫秒)

nx,如果设置为True,则只有name不存在时,当前set操作才执行

xx,如果设置为True,则只有name存在时,当前set操作才执行

String操作:

  • setnx:设置值,只有name不存在时,执行设置操作(添加)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red = redis.Redis(host='172.1.1.7',port=6379)
r=red.setnx('kk','vv') #setnx设置值,只有name不存在时,执行设置操作(添加)
print(red.get('kk')) #打印key对应的值
  • setex:设置超时时间(超时时间过后,key value失效)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
import time
red = redis.Redis(host='172.1.1.7',port=6379)
red.setex('kk1','vv1',2) #设置有效时长为2
print(red.get('kk1'))
time.sleep(3) #3秒超时
print(red.get('kk1')) #返回值为空
  • mset&mget:批量设置值
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red=redis.Redis(host='172.1.1.7',port=6379)
red.set('k6','v7') #单个设值
red.mset(k1='v1',k2='v2',k3='v3') #第一种方法设值
red.mset({'k4':'v4','k5':'v5'}) #第二种方法
print(red.mget('k1','k2')) #多个取值
print(red.get('k3')) #单个取值
  • getset:设置新值并获取原来的值
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red = redis.Redis(host='172.1.1.7',port=6379)
red.set('k1','vvv')
print(red.getset('k1','afternew')) #设置新值,返回旧值
print(red.get('k1')) #此时是新值
  • getrange:获取子序列
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red=redis.Redis(host='172.1.1.7',port=6379)
red.set('k1','我爱北京天安门')
tt=red.getrange('k1',0,3)
print(red.getrange('k1',0,3)) #汉子的话是每三个字节算一个汉子
  • setrange(name, offset, value):修改字符串内容,从指定字符串索引开始向后替换(新值太长时,则向后添加)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red=redis.Redis(host='172.1.1.7',port=6379)
red.set('k1','我爱北京天安门')
print(red.setrange('k1',3,'hah'))
  • setbit(name, offset, value):对name对应值的二进制表示的位进行操作
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red=redis.Redis(host='172.1.1.7',port=6379)
red.set('k1','vava')
red.setbit('k1',7,1) #将第七位设置成一
print(red.get('k1'))
source = "哈哈哈"
for i in source:
num=ord(i)
print(bin(num).replace('b','')) #打印二进制格式字符串
  • getbit(name, offset):获取name对应的值的二进制表示中的某位的值 (0或1)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red=redis.Redis(host='172.1.1.7',port=6379)
red.set('k1','abc')
print(red.getbit('k1',2))
  • bitcount(key, start=None, end=None):获取name对应的值的二进制表示中 1 的个数
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red=redis.Redis(host='172.1.1.7',port=6379)
red.set('k1','abc')
print(red.bitcount('k1',0,8))
  • bitop(operation, dest, *keys):获取多个值,并将值做位运算,将最后的结果保存至新的name对应的值
    • 参数:
      • operation:AND,OR,NOT,XOR
      • dest:new data
      • src:source data
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red=redis.Redis(host='172.1.1.7',port=6379)
red.set('k1','abc')
print(red.bitop('AND','kk','k1'))
  • strlen(name):返回name对应值的字节长度(一个汉字3个字节)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red=redis.Redis(host='172.1.1.7',port=6379)
red.set('k1','abc')
print(red.strlen('k1'))
  • incr(self, name, amount=1):自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增
  • decr(self, name, amount=1):自减name对应的值
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red=redis.Redis(host='172.1.1.7',port=6379)
red.set('k1','12345') #确保value是整数
print(red.incr('k1',amount=1)) #amount代表步进值
  • incrbyfloat(self, name, amount=1.0)   带浮点的自增
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red=redis.Redis(host='172.1.1.7',port=6379)
red.set('k1','12345.999') #确保value是整数或者浮点数
print(red.incrbyfloat('k1',amount=0.1))
  • append(key, value):追加模式
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red=redis.Redis(host='10.70.18.66',port=6379)
red.set('k1','v1')
red.append('k1','v2') #对应的k1键值后面追加v2,
print(red.get('k1')) #结果b'v1v2'

Hash操作

redis中Hash在内存中的存储格式如下图:

  • hset(‘name’,’key’,’value’)&hget(’name’,’key’),getall(‘name’):设置和获取哈希值
import redis
red=redis.Redis(host='10.70.18.100',port=6379)
red.hset("a1","k1","v1")
print(red.hget('a1','k1')) #要有key和对应的hash键b'v1'
print(red.hgetall('a1')) #获取全部{b'k1': b'v1'}
  • mset(name, mapping)&mget(name, mapping)&getall()
import redis
red=redis.Redis(host='10.70.18.100',port=6379)
dic={'k1':'v1','k2':'v20'}
red.hmset('a2',dic)
print(red.hget('a2','k1')) #返回值b'v1'
print(red.hgetall('a2')) #返回一个字典
  • hlen(name):获取name对应的hash中键值对的个数
import redis
red=redis.Redis(host='10.70.18.100',port=6379)
dic={'k1':'v1','k2':'v20'}
red.hmset('a2',dic)
print(red.hgetall('a2')) #返回一个字典
print(red.hlen('a2')) #打印元素个数
  • hkeys(name):获取name对应的hash中所有的key的值
import redis
red=redis.Redis(host='10.70.18.100',port=6379)
dic={'k1':'v1','k2':'v20'}
red.hmset('a2',dic)
print(red.hgetall('a2')) #返回一个字典
print(red.hkeys('a2')) #打印key
  • hvals(name):获取name对应的hash中所有的value的值
import redis
red=redis.Redis(host='10.70.18.100',port=6379)
dic={'k1':'v1','k2':'v20'}
red.hmset('a2',dic)
print(red.hvals('a2')) #打印value值
  • hexists(name, key):检查name对应的hash是否存在当前传入的key
import redis
red=redis.Redis(host='10.70.18.100',port=6379)
dic={'k1':'v1','k2':'v20'}
red.hmset('a2',dic)
print(red.hexists('a2','ds')) #是否存在a2对应的ds,返回False
  • hdel(name,*keys):将name对应的hash中指定key的键值对删除
import redis
red=redis.Redis(host='10.70.18.100',port=6379)
dic={'k1':'v1','k2':'v20'}
red.hmset('a2',dic)
print(red.hdel('a2','k1')) #删除对应的a2对应的看k1
  • hincrby(name, key, amount=1):自增name对应的hash中的指定key的值,不存在则创建key=amount
  • hincrbyfloat(name, key, amount=1.0):自增name对应的hash中的指定key的值,不存在则创建key=amount
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red=redis.Redis(host='10.70.18.100',port=6379)
dic={'k1':'999','k2':'111'}
red.hmset('a2',dic)
print(red.hincrby('a2','k1',amount=100)) #获取到的值自增amount值
print(red.hincrbyfloat('a2','k2',amount=199.999)) #获取到的值自增amount值
  • hscan(name, cursor=0, match=None, count=None):增量式迭代获取,对于数据大的数据非常有用,hscan可以实现分片的获取数据,并非一次性将数据全部获取完,从而防止内存被撑爆
# 增量式迭代获取,对于数据大的数据非常有用,hscan可以实现分片的获取数据,并非一次性将数据全部获取完,从而放置内存被撑爆

# 参数:
# name,redis的name
# cursor,游标(基于游标分批取获取数据)
# match,匹配指定key,默认None 表示所有的key
# count,每次分片最少获取个数,默认None表示采用Redis的默认分片个数 # 如:
# 第一次:cursor1, data1 = r.hscan('xx', cursor=0, match=None, count=None)
# 第二次:cursor2, data1 = r.hscan('xx', cursor=cursor1, match=None, count=None)
# ...
# 直到返回值cursor的值为0时,表示数据已经通过分片获取完毕
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red=redis.Redis(host='10.70.18.100',port=6379)
dic={'k1':'999','k2':'111'}
dic1={'k3':'2asd','k4':'dadsadadsd'}
red.hmset('a2',dic)
red.hmset('a3',dic1) cursor1,data=red.hscan('a2',cursor=0,match=None,count=None)
print(cursor1,data)
cursor2,data2=red.hscan('a3',cursor=0,match=None,count=None)
print(cursor2,data2)
  • hscan_iter(name, match=None, count=None):利用yield封装hscan创建生成器,实现分批去redis中获取数据
# 利用yield封装hscan创建生成器,实现分批去redis中获取数据

# 参数:
# match,匹配指定key,默认None 表示所有的key
# count,每次分片最少获取个数,默认None表示采用Redis的默认分片个数 # 如:
# for item in r.hscan_iter('xx'):
# print item

List操作

redis中的List在在内存中按照一个name对应一个List来存储。如图:

  • lpush(name,values):在name对应的list中添加元素,每个新的元素都添加到列表的最左边
  • rpush(name, values) :表示从右向左操作
  • lpop(name):在name对应的列表的左侧获取第一个元素并在列表中移除,返回值则是第一个元素
  • rpop(name): 表示从右向左操作
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red=redis.Redis(host='10.70.18.100',port=6379)
red.lpush('k2',11,22,33,44) #左插入
print(red.lpop('k2')) #左取值,右出栈----》b'44'
print(red.rpop('k2')) #右取值,左出栈----》b'11'
red.rpush('k3',12,1111) #右插入
print(red.rpop('k3')) #右弹出
print(red.lpop('k3')) #左弹出
  • lpushx(name,value):在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边
  • rpushx(name, value): 表示从右向左操作
  • llen(name):name对应的list元素的个数
  • r.lset(name, index, value):对name对应的list中的某一个索引位置重新赋值
  • r.lrem(name, value, num):在name对应的list中删除指定的值
  • brpoplpush(src, dst, timeout=0):从一个列表的右侧移除一个元素并将其添加到另一个列表的左侧
  • blpop(keys, timeout):将多个列表排列,按照从左到右去pop对应列表的元素
  • rpoplpush(src, dst):从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边
  • ltrim(name, start, end):在name对应的列表中移除没有在start-end索引之间的值
  • lrange(name, start, end):在name对应的列表分片获取数据
  • lindex(name, index):在name对应的列表中根据索引获取列表元素
  • 自定义增量迭代
# 由于redis类库中没有提供对列表元素的增量迭代,如果想要循环name对应的列表的所有元素,那么就需要:
# 1、获取name对应的所有列表
# 2、循环列表
# 但是,如果列表非常大,那么就有可能在第一步时就将程序的内容撑爆,所有有必要自定义一个增量迭代的功能: def list_iter(name):
"""
自定义redis列表增量迭代
:param name: redis中的name,即:迭代name对应的列表
:return: yield 返回 列表元素
"""
list_count = r.llen(name)
for index in xrange(list_count):
yield r.lindex(name, index) # 使用
for item in list_iter('pp'):
print item

Set操作,Set集合就是不允许重复的列表

更多详情参考:http://www.cnblogs.com/wupeiqi/articles/5132791.html

管道

redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
red=redis.ConnectionPool(host='10.70.18.100',port=6379) #创建连接池
red_s=redis.Redis(connection_pool=red) pipe=red_s.pipeline(transaction=True)
# pipe=red_s.pipeline(transaction=False)
pipe.set('name',"hehehe")
pipe.set('role','sbbb')
pipe.execute()

发布订阅

helper:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis class RedisHelper:
def __init__(self):
self.__conn = redis.Redis(host='10.70.18.100')
self.chan_sub = 'fm104.5'
self.chan_pub = 'fm104.5' def public(self, msg):
self.__conn.publish(self.chan_pub, msg)
return True def subscribe(self):
pub = self.__conn.pubsub()
pub.subscribe(self.chan_sub)
pub.parse_response()
return pub

publisher:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from redis_helper import RedisHelper
obj = RedisHelper()
obj.public('hello')

receiver:

#!/usr/bin/env python
# -*- coding:utf-8 -*- from redis_helper import RedisHelper
obj=RedisHelper()
redis_sub=obj.subscribe()
while True:
msg = redis_sub.parse_response()
print(msg)

day13 memcache,redis上篇的更多相关文章

  1. ehcache memcache redis -- java中的三大缓存

      三个缓存在java代码中用的是较多的,但是它们都有自己的应用场合,和优缺点.  Ehcache 1.初衷:减少数据库操作的高延时而设计.(缓存的目的,好像都是这个吧) 2.Apache Licen ...

  2. 缓存子系统如何设计(Cachable tag, Memcache/redis support, xml config support, LRU/LFU/本地缓存命中率)

    大家对这段代码肯定很熟悉吧: public List<UserInfo> SearchUsers(string userName) { string cacheKey=string.For ...

  3. 分布式缓存集群方案特性使用场景(Memcache/Redis(Twemproxy/Codis/Redis-cluster))优缺点对比及选型

    分布式缓存集群方案特性使用场景(Memcache/Redis(Twemproxy/Codis/Redis-cluster))优缺点对比及选型   分布式缓存特性: 1) 高性能:当传统数据库面临大规模 ...

  4. ehcache memcache redis 三大缓存

    最近项目组有用到这三个缓存,去各自的官方看了下,觉得还真的各有千秋!今天特意归纳下各个缓存的优缺点,仅供参考!  Ehcache 在Java项目广泛的使用.它是一个开源的.设计于提高在数据从RDBMS ...

  5. Memcache,Redis,MongoDB(数据缓存系统)方案对比与分析

    mongodb和memcached不是一个范畴内的东西.mongodb是文档型的非关系型数据库,其优势在于查询功能比较强大,能存储海量数据.mongodb和memcached不存在谁替换谁的问题. 和 ...

  6. ehcache memcache redis 三大缓存男高音

    最近项目组有用到这三个缓存,去各自的官方看了下,觉得还真的各有千秋!今天特意归纳下各个缓存的优缺点,仅供参考!  Ehcache 在java项目广泛的使用.它是一个开源的.设计于提高在数据从RDBMS ...

  7. memcache/redis 缓存学习笔记

    0.redis和memcache的区别 a.redis可以存储除了string之外的对象,如list,hash等 b.服务器宕机以后,redis会把内存的数据持久化到磁盘上,而memcache则不会 ...

  8. FW:: ehcache memcache redis 三大缓存男高音

    最近项目组有用到这三个缓存,去各自的官方看了下,觉得还真的各有千秋!今天特意归纳下各个缓存的优缺点,仅供参考!  Ehcache 在java项目广泛的使用.它是一个开源的.设计于提高在数据从RDBMS ...

  9. NoSQL分类及ehcache memcache redis 三大缓存的对比

    NoSQL分类 由于NoSQL中没有像传统数据库那样定义数据的组织方式为关系型的,所以只要内部的数据组织采用了非关系型的方式,就可以称之为NoSQL数据库.目前,可以将众多的NoSQL数据库按照内部的 ...

随机推荐

  1. C#可扩展编程之MEF(一):MEF简介及简单的Demo

      在文章开始之前,首先简单介绍一下什么是MEF,MEF,全称Managed Extensibility Framework(托管可扩展框架).单从名字我们不难发现:MEF是专门致力于解决扩展性问题的 ...

  2. ROCR包中ROC曲线计算是取大于cutoff还是大于等于cutoff

    找到对应的代码如下 .compute.unnormalized.roc.curve function (predictions, labels) { pos.label <- levels(la ...

  3. PAT甲级——A1025 PAT Ranking

    Programming Ability Test (PAT) is organized by the College of Computer Science and Technology of Zhe ...

  4. Webpack下创建vue项目-非vue-cli

    开始准备 初始化工程目录 shell npm init -y 安装vue npm install vue 安装 webpack npm install webpack --save-dev webpa ...

  5. eureka添加security验证之后,client注册失败

    高版本,以下配置已弃用 security: basic: enabled: true 所以需要自定义security配置开启basic认证,参考我的配置类 @Configuration @Enable ...

  6. 2018-11-19-windows-应用程序在关机时的退出代号

    title author date CreateTime categories windows 应用程序在关机时的退出代号 lindexi 2018-11-19 14:31:38 +0800 2018 ...

  7. vue实现跳转路由

    参考vue官方文档:https://router.vuejs.org/zh/guide/essentials/navigation.html // 字符串 router.push('home') // ...

  8. Broken Keyboard UVA 11988 数组实现链表

    这个构造十分巧妙,,,又学到一招,有点类似数组实现的邻接表 #include <iostream> #include <string.h> #include <cstdi ...

  9. 【vue】imitate-beautiful-thing

    我从未见过这么美妙的项目,当然与我接触的项目少有关,但是这个项目满满的艺术气息,让人沉醉,让人忍不住的去研究代码. 先放项目地址:https://github.com/eidonlon/imitate ...

  10. Jboss 默认加载项目访问

    修改JBOSS的server.xml路径为: D:\Program Files\jboss-4.2.2.GA\server\default\deploy\jboss-web.deployer\serv ...