Memcache

Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。

安装

pip3 install python-memcached

连接

import memcache

# 连接服务器
mc = memcache.Client(['10.211.55.5:11211'], debug=True) # 添加数据
mc.set("foo","bar")
# 获取数据
ret = mc.get('foo')
print(ret)

memcache 模块支持集群操作,其原理是在内存为维护一个主机列表,且集群主机的权重值与主机在列表中出现的次数成正比

# servers 是一个以元组为元素的列表,元组的元素为 IP地址:端口和权重值
# 由于第二个 server 的权重为 2,所以在内存中维护的列表,第二个 server 出现 2 次
# 在内存中维护的列表为 ['1.1.1.1:12000', '1.1.1.2:12000', '1.1.1.2:12000', '1.1.1.3:12000'] mc = memcache.Client([('1.1.1.1:12000', 1), ('1.1.1.2:12000', 2), ('1.1.1.3:12000', 1)], debug=True) # 当 servers 为集群时,在将数据存储到集群中时需要:
# 1、将 "k" 根据算法转换为一个数字
# 2、使用这个数字与列表的数量求余数
# 3、以余数为索引在列表中获取 server
# 4、将数据存在到 server mc.set("k", "v")

方法

  • add  添加一条键值对,如果 key 已经存在,则出现异常
  • replace 修改指定 key 的值,如果 key 不存在则报错
  • set 设置一个键值对,如果 key 存在则修改,如果 key 不存在则创建
  • set_multi 设置多个键值对,如果 key 存在则修改,如果 key 不存在则创建
  • delete 删除指定 key 的键值对
  • delete_multi 删除列表中 key 的键值对
  • get 获取指定 key 的值并返回
  • get_multi 获取列表中 key 的键值对并以字典的形式返回
  • append 修改指定 key 的值,在该值后面追加内容
  • prepend 修改指定 key 的值,在该值前面插入内容
  • incr 自增,将指定 key 的值增加 N,默认为 1
  • decr 自减,将指定 key 的值减少 N,默认为 1
  • gets 和 cas 配合使用,通过 gets 数据时,会从服务器端获取一个自增的数字,而通过 cas 修改数据时会将这个数字发送给服务器,服务器将两个数字比较,如果相等则允许修改,否则不允许修改。
mc = memcache.Client(['10.211.55.5:11211'], debug=True)

mc.add("name","Cain")  # 添加第一条数据
mc.add("name","Alan") # 添加相同 key 则会报错“MemCached: while expecting 'STORED', got unexpected response 'NOT_STORED'” mc.replace("name","Alan") # 修改 name 的值为 Alan mc.set("age", 10) # 设置一条数据 age 等于 10
mc.set("age", 11) # 设置一天数据,由于 age 已经存在,会将 age 修改为 11 mc.set_multi({"name":"Cain", "age": 100}) # 设置多条数据 mc.delete("name") # 删除一条数据,如果 key 不存在则报错
mc.delete_multi(["name", "age"]) # 删除多条数据 r = mc.get("name") # 获取一条数据
r_dict = mc.get_multi(["name","age"]) # 获取多个键值对,以字典形式返回 mc.append("name", "after") # 在 name 的值后面添加 after
mc.prepend("name", "brfore") # 在 name 的值前面插入 before mc.incr('age', "") # 将 age 的值增加 100
mc.incr('age', 100) mc.decr('age', '') # 将 age 的值减少 99
mc.decr('age', 99) # gets 取数据之后无其他程序获取过则修改成功
age = mc.gets("age")
mc.cas("age", 400) age1 = mc.gets('age')
# 另外一个程序获取了 age,程序会报错
mc.cas("age", 500)

Redis

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

参考:http://www.cnblogs.com/wupeiqi/articles/5132791.html

安装

# pip3 install redis

连接

import redis

# 第一种方式
r = redis.Redis(host='10.211.55.5', port=6379) # 第二种方式
# r = redis.StrictRedis(host='10.211.55.5', port=6379) # 第三种方式,连接池
# pool = redis.ConnectionPool(host='10.211.55.5', port=6379)
# r = redis.Redis(connection_pool=pool) r.set("foo", 'bar')
print(r.get("foo").decode())

操作

redis 的操作分为:

  • key 操作
  • string 操作
  • hash 操作
  • list 操作
  • set 操作
  • sort set 操作

key 操作:

  • delete 删除指定的 key
  • exists 检查指定的 key 是否存在
  • expire 为指定的 key 设置过期时间
  • persist 移除指定 key 的过期时间,key 将持久保持
  • type 返回 key 对应值的类型
# 连接 redis,并添加两个 key
r = redis.Redis(host='10.211.55.5', port=6379)
r.set("foo1", 'bar')
r.set("foo2", 'bar') r.delete('foo1') # 删除指定的 key print(r.exists('foo2')) # 检查 key 是否存在,存在则返回 True r.expire('foo2', 60) # 为指定的 key 设置过期时间 r.persist('foo2') # 移除指定 key 的过期时间 print(r.type('foo2')) # 返回 key 对应值的类型

string 操作:

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

在Redis中设置值,默认,不存在则创建,存在则修改
参数:
ex,过期时间(秒)
px,过期时间(毫秒)
nx,如果设置为True,则只有name不存在时,当前set操作才执行
xx,如果设置为True,则只有name存在时,岗前set操作才执行

setnx(name, value)

设置值,只有name不存在时,执行设置操作(添加),执行成功返回 True,否则返回 False

setex(name, value, time)

# 设置值
# 参数:
# time,过期时间(数字秒 或 timedelta对象)

psetex(name, time_ms, value)

# 设置值
# 参数:
# time_ms,过期时间(数字毫秒 或 timedelta对象)

mset(*args, **kwargs)

批量设置值
如:
mset(name='Cain',age='10')

mget({'name': 'Cain', 'age': '10'})

get(name)

获取值

mget(keys, *args)

批量获取
如:
mget('name', 'age')

r.mget(['name', 'age'])

getset(name, value)

设置新值并获取原来的值

getrange(key, start, end)

# 获取子序列(根据字节获取,非字符)
# 参数:
# name,Redis 的 name
# start,起始位置(字节)
# end,结束位置(字节)
# 如: "Cain" ,0-2表示 "Cai" "学习", 0-2 表示 "学" b'\xe5\xad\xa6'
# 注:和列表字符串截取不同,end 表示的字节也会被截取到

setrange(name, offset, value)

# 修改字符串内容,从指定字符串索引开始向后替换(新值太长时,则向后添加)
# 参数:
# offset,字符串的索引,字节(一个汉字三个字节)
# value,要设置的值
# 如: 修改第二个汉字 setrange('name', 3, '啊')

setbit(name, offset, value)

# 对name对应值的二进制表示的位进行操作

# 参数:
# name,redis的name
# offset,位的索引(将值变换成二进制后再进行索引)
# value,值只能是 1 或 0 # 注:如果在Redis中有一个对应: name = "foo",
那么字符串foo的二进制表示为:01100110 01101111 01101111
所以,如果执行 setbit('name', 7, 1),则就会将第7位设置为1,
那么最终二进制则变成 01100111 01101111 01101111,即:"goo" # 扩展,转换二进制表示:
source = "foo"
for i in source:
num = ord(i)
print bin(num).replace('b','')

getbit(name, offset)

# 获取name对应的值的二进制表示中的某位的值 (0或1)

bitcount(key, start=None, end=None)

# 获取name对应的值的二进制表示中 1 的个数
# 参数:
# key,Redis的name
# start,位起始位置
# end,位结束位置
# 如:统计第一个字节有几个1, bitcount('name',0,0)

bitop(operation, dest, *keys)

# 获取多个值,并将值做位运算,将最后的结果保存至新的name对应的值

# 参数:
# operation,AND(并) 、 OR(或) 、 NOT(非) 、 XOR(异或)
# dest, 新的Redis的name
# *keys,要查找的Redis的name # 如:
bitop("AND", 'new_name', 'n1', 'n2', 'n3')
# 获取Redis中n1,n2,n3对应的值,然后讲所有的值做位运算(求并集),然后将结果保存 new_name 对应的值中

strlen(name)

# 返回name对应值的字节长度(一个汉字3个字节)

incr(self, name, amount=1)

# 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。

# 参数:
# name,Redis的name
# amount,自增数(必须是整数)
  
# 注:同incrby , name 对应的值也必须是整数才能自增

incrbyfloat(self, name, amount=1.0)

# 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。

# 参数:
# name,Redis的name
# amount,自增数(浮点型)

decr(self, name, amount=1)

# 自减 name对应的值,当name不存在时,则创建name=amount,否则,则自减。

# 参数:
# name,Redis的name
# amount,自减数(整数)

append(key, value)

# 在redis name对应的值后面追加内容

# 参数:
key, redis的name
value, 要追加的字符串

 Hash操作

hset(name, key, value)

# name对应的hash中设置一个键值对(不存在,则创建;否则,修改)

# 参数:
# name,redis的name
# key,name对应的hash中的key
# value,name对应的hash中的value # 注:
# hsetnx(name, key, value),当name对应的hash中不存在当前key时则创建(相当于添加)

hmset(name, mapping)

# 在name对应的hash中批量设置键值对

# 参数:
# name,redis的name
# mapping,字典,如:{'k1':'v1', 'k2': 'v2'} # 如:
# r.hmset('xx', {'k1':'v1', 'k2': 'v2'})

hget(name,key)

# 在name对应的hash中获取根据key获取value

hmget(name, keys, *args)

# 在name对应的hash中获取多个key的值

# 参数:
# name,reids对应的name
# keys,要获取key集合,如:['k1', 'k2', 'k3']
# *args,要获取的key,如:k1,k2,k3 # 如:
# r.mget('xx', ['k1', 'k2'])
# 或
# print r.hmget('xx', 'k1', 'k2')

hgetall(name)

获取name对应hash的所有键值

hlen(name)

# 获取name对应的hash中键值对的个数

hkeys(name)

# 获取name对应的hash中所有的key的值

hvals(name)

# 获取name对应的hash中所有的value的值

hexists(name, key)

# 检查name对应的hash是否存在当前传入的key

hdel(name,*keys)

# 将name对应的hash中指定key的键值对删除

hincrby(name, key, amount=1)

# 自增name对应的hash中的指定key的值,不存在则创建key=amount
# 参数:
# name,redis中的name
# key, hash对应的key
# amount,自增数(整数)

hincrbyfloat(name, key, amount=1.0)

# 自增name对应的hash中的指定key的值,不存在则创建key=amount

# 参数:
# name,redis中的name
# key, hash对应的key
# amount,自增数(浮点数) # 自增name对应的hash中的指定key的值,不存在则创建key=amount

hscan(name, cursor=0, match=None, count=None)

# 增量式迭代获取,对于数据大的数据非常有用,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时,表示数据已经通过分片获取完毕

hscan_iter(name, match=None, count=None)

# 利用yield封装hscan创建生成器,实现分批去redis中获取数据

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

 List 操作:

lpush(name,values)

# 在name对应的list中添加元素,每个新的元素都添加到列表的最左边

# 如:
# r.lpush('oo', 11,22,33)
# 保存顺序为: 33,22,11 # 扩展:
# rpush(name, values) 表示从右向左操作

lpushx(name,value)

# 在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边

# 更多:
# rpushx(name, value) 表示从右向左操作

llen(name)

# name对应的list元素的个数

linsert(name, where, refvalue, value))

# 在name对应的列表的某一个值前或后插入一个新值

# 参数:
# name,redis的name
# where,BEFORE或AFTER
# refvalue,标杆值,即:在它前后插入数据
# value,要插入的数据

r.lset(name, index, value)

# 对name对应的list中的某一个索引位置重新赋值

# 参数:
# name,redis的name
# index,list的索引位置
# value,要设置的值

r.lrem(name, value, num)

# 在name对应的list中删除指定的值

# 参数:
# name,redis的name
# value,要删除的值
# num, num=0,删除列表中所有的指定值;
# num=2,从前到后,删除2个;
# num=-2,从后向前,删除2个

lpop(name)

# 在name对应的列表的左侧获取第一个元素并在列表中移除,返回值则是第一个元素

# 更多:
# rpop(name) 表示从右向左操作

lindex(name, index)

在name对应的列表中根据索引获取列表元素

lrange(name, start, end)

# 在name对应的列表分片获取数据
# 参数:
# name,redis的name
# start,索引的起始位置
# end,索引结束位置

ltrim(name, start, end)

# 在name对应的列表中移除没有在start-end索引之间的值
# 参数:
# name,redis的name
# start,索引的起始位置
# end,索引结束位置

rpoplpush(src, dst)

# 从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边
# 参数:
# src,要取数据的列表的name
# dst,要添加数据的列表的name

blpop(keys, timeout)

# 将多个列表排列,按照从左到右去pop对应列表的元素

# 参数:
# keys,redis的name的集合
# timeout,超时时间,当元素所有列表的元素获取完之后,阻塞等待列表内有数据的时间(秒), 0 表示永远阻塞 # 更多:
# r.brpop(keys, timeout),从右向左获取数据

brpoplpush(src, dst, timeout=0)

# 从一个列表的右侧移除一个元素并将其添加到另一个列表的左侧

# 参数:
# src,取出并要移除元素的列表对应的name
# dst,要插入元素的列表对应的name
# timeout,当src对应的列表中没有数据时,阻塞等待其有数据的超时时间(秒),0 表示永远阻塞

自定义增量迭代

# 由于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操作:

sadd(name,values)

# name对应的集合中添加元素

scard(name)

# 获取name对应的集合中元素个数

sdiff(keys, *args)

# 在第一个name对应的集合中且不在其他name对应的集合的元素集合

sdiffstore(dest, keys, *args)

# 获取第一个name对应的集合中且不在其他name对应的集合,再将其新加入到dest对应的集合中

sinter(keys, *args)

# 获取多一个name对应集合的并集

sinterstore(dest, keys, *args)

# 获取多一个name对应集合的并集,再讲其加入到dest对应的集合中

sismember(name, value)

# 检查value是否是name对应的集合的成员

smembers(name)

# 获取name对应的集合的所有成员

smove(src, dst, value)

# 将某个成员从一个集合中移动到另外一个集合

spop(name)

# 从集合的右侧(尾部)移除一个成员,并将其返回

srandmember(name, numbers)

# 从name对应的集合中随机获取 numbers 个元素

srem(name, values)

# 在name对应的集合中删除某些值

sunion(keys, *args)

# 获取多一个name对应的集合的并集

sunionstore(dest,keys, *args)

# 获取多一个name对应的集合的并集,并将结果保存到dest对应的集合中

sscan(name, cursor=0, match=None, count=None)

sscan_iter(name, match=None, count=None)

# 同字符串的操作,用于增量迭代分批获取元素,避免内存消耗太大

 有序集合操作:

zadd(name, *args, **kwargs)

# 在name对应的有序集合中添加元素
# 如:
# zadd('zz', 'n1', 1, 'n2', 2)
# 或
# zadd('zz', n1=11, n2=22)

zcard(name)

# 获取name对应的有序集合元素的数量

zcount(name, min, max)

# 获取name对应的有序集合中分数 在 [min,max] 之间的个数

zincrby(name, value, amount)

# 自增name对应的有序集合的 name 对应的分数

zrange( name, start, end, desc=False, withscores=False, score_cast_func=float)

# 按照索引范围获取name对应的有序集合的元素

# 参数:
# name,redis的name
# start,有序集合索引起始位置(非分数)
# end,有序集合索引结束位置(非分数)
# desc,排序规则,默认按照分数从小到大排序
# withscores,是否获取元素的分数,默认只获取元素的值
# score_cast_func,对分数进行数据转换的函数 # 更多:
# 从大到小排序
# zrevrange(name, start, end, withscores=False, score_cast_func=float) # 按照分数范围获取name对应的有序集合的元素
# zrangebyscore(name, min, max, start=None, num=None, withscores=False, score_cast_func=float)
# 从大到小排序
# zrevrangebyscore(name, max, min, start=None, num=None, withscores=False, score_cast_func=float)

zrank(name, value)

# 获取某个值在 name对应的有序集合中的排行(从 0 开始)

# 更多:
# zrevrank(name, value),从大到小排序

zrangebylex(name, min, max, start=None, num=None)

# 当有序集合的所有成员都具有相同的分值时,有序集合的元素会根据成员的 值 (lexicographical ordering)来进行排序,而这个命令则可以返回给定的有序集合键 key 中, 元素的值介于 min 和 max 之间的成员
# 对集合中的每个成员进行逐个字节的对比(byte-by-byte compare), 并按照从低到高的顺序, 返回排序后的集合成员。 如果两个字符串有一部分内容是相同的话, 那么命令会认为较长的字符串比较短的字符串要大 # 参数:
# name,redis的name
# min,左区间(值)。 + 表示正无限; - 表示负无限; ( 表示开区间; [ 则表示闭区间
# min,右区间(值)
# start,对结果进行分片处理,索引位置
# num,对结果进行分片处理,索引后面的num个元素 # 如:
# ZADD myzset 0 aa 0 ba 0 ca 0 da 0 ea 0 fa 0 ga
# r.zrangebylex('myzset', "-", "[ca") 结果为:['aa', 'ba', 'ca'] # 更多:
# 从大到小排序
# zrevrangebylex(name, max, min, start=None, num=None)

zrem(name, values)

# 删除name对应的有序集合中值是values的成员

# 如:zrem('zz', ['s1', 's2'])

zremrangebyrank(name, min, max)

# 根据排行范围删除

zremrangebyscore(name, min, max)

# 根据分数范围删除

zremrangebylex(name, min, max)

# 根据值返回删除

zscore(name, value)

# 获取name对应有序集合中 value 对应的分数

zinterstore(dest, keys, aggregate=None)

# 获取两个有序集合的交集,如果遇到相同值不同分数,则按照aggregate进行操作
# aggregate的值为: SUM MIN MAX

zunionstore(dest, keys, aggregate=None)

# 获取两个有序集合的并集,如果遇到相同值不同分数,则按照aggregate进行操作
# aggregate的值为: SUM MIN MAX

zscan(name, cursor=0, match=None, count=None, score_cast_func=float)
 zscan_iter(name, match=None, count=None,score_cast_func=float)

# 同字符串相似,相较于字符串新增score_cast_func,用来对分数进行操作

管道

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

import redis

pool = redis.ConnectionPool(host='10.211.55.5', port=6379)

r = redis.Redis(connection_pool=pool)

# pipe = r.pipeline(transaction=False)
pipe = r.pipeline(transaction=True) r.set('name', 'Cain')
r.set('age', '') pipe.execute()

发布订阅

发布者:服务器

订阅者:Dashboad和数据处理

Demo如下:

import redis

class RedisHelper:

    def __init__(self):
self.__conn = redis.Redis(host='10.211.55.5')
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

订阅者

from monitor import RedisHelper

obj = RedisHelper()
redis_sub = obj.subscribe() while True:
msg= redis_sub.parse_response()
print(msg)

发布者

from monitor import RedisHelper

obj = RedisHelper()
obj.public('hello')

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. DIV+CSS布局-固定页面开度布局

    DIV+CSS布局中主要CSS属性介绍: Float: Float属性是DIV+CSS布局中最基本也是最常用的属性,用于实现多列功能,我们知道<div>标签默认一行只能显示一个,而使用Fl ...

  2. Yii 安装二维码扩展Qrcode

    比如要添加 https://github.com/2amigos/yii2-qrcode-helper 生成二维码的 这个扩展第一种方法 :    1.打开根目录的composer.json, 在re ...

  3. 【转】android多分辨率适配

    前一阶段开发android项目,由于客户要求进行多分辨率适配,能够支持国内主流的分辨率手机.因此经过了几次开发走了很多弯路,目前刚刚领略了android多分辨率适配的一些方法. 先介绍一下所走的弯路, ...

  4. ACM 关于数据输入加速

    转载请注明出处:http://blog.csdn.net/a1dark 分析:我们都知道运行时间对我们来说很重要.有时候不惜用大量的内存去换取一点时间.有些人可能都比较关注这个问题.首先时间上:cin ...

  5. Swift 实现图片转字符画的功能

    本文介绍一个IOS APP , 将图片转换成ASCII字符画,使用Swift语言编写. 举个例子,我们使用著名的蕾娜照片作为原图片 经APP转换后形成的字符画,我们打印出来,效果如下: 放大她的脸部可 ...

  6. mysql触发器的作用及语法

    触发器是一种特殊的存储过程,它在插入,删除或改动特定表中的数据时触发运行,它比数据库本身标准的功能有更精细和更复杂的数据控制能力. 数据库触发器有下面的作用: 1.安全性.能够基于数据库的值使用户具有 ...

  7. MYSQL 5.7 MTS 复制

    http://www.linuxidc.com/Linux/2013-04/82712p2.htm http://keithlan.github.io/2016/06/28/MTS/ http://d ...

  8. SOA体系结构之基础培训教程-大纲篇

    引言: 最近受邀做了一个企业的SOA体系结构的内训,本文是内训课程的培训大纲,分享一下吧,希望大家能够喜欢.同时也想针对大纲中列出的内容对SOA架构体系做一次回顾,如果时间允许把完整的课件也想放上来共 ...

  9. android开发之单点触摸

    相对于多点触摸,单点触摸还是很简单的. 新建一个工程,先看看布局文件: <RelativeLayout xmlns:android="http://schemas.android.co ...

  10. Winform中修改WebBrowser控件User-Agent的方法(已经测试成功)

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.W ...