Python + redis操作Redis数据库
Redis
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都 支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排 序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文 件,并且在此基础上实现了master-slave(主从)同步。
一、Python操作Redis
API使用
redis-py 的API的使用可以分类为:
- 连接方式
- 连接池
- 操作
- String 操作
- Hash 操作
- List 操作
- Set 操作
- Sort Set 操作
- 管道
- 发布订阅
1、操作模式
redis-py提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令,Redis是StrictRedis的子类,用于向后兼容旧版本的redis-py。
#!/usr/bin/env python
# -*- coding:utf-8 -*- import redis r = redis.Redis(host='192.168.1.113', port=6379)
r.set('foo', 'Bar')
print r.get('foo')
2、连接池
redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数 Redis,这样就可以实现多个Redis实例共享一个连接池。
#!/usr/bin/env python
# -*- coding:utf-8 -*- import redis pool = redis.ConnectionPool(host='192.168.1.113', port=6379) r = redis.Redis(connection_pool=pool)
r.set('foo', 'Bar')
print r.get('foo')
3、操作
String操作,redis中的String在在内存中按照一个name对应一个value来存储。如图:
set(name, value, ex=None, px=None, nx=False, xx=False)
在Redis中设置值,默认,不存在则创建,存在则修改
参数:
ex,过期时间(秒)
px,过期时间(毫秒)
nx,如果设置为True,则只有name不存在时,当前set操作才执行
xx,如果设置为True,则只有name存在时,岗前set操作才执行 r.get("name") # 获取字段
b'haha'
r.set("name", "hehe", ex=5) # 保留时长 5秒
r.get("name")
b'hehe'
r.get("name")
r.set({'k1': 'v1', 'k2': 'v2'}) # 支持字典格式
r.get("k1")
b'v1'
mset(*args, **kwargs)
# 批量设置
r.mset(name="xixi", age=18)
r.get("name")
b'xixi'
r.get("age")
b'18'
mget(keys, *args)
# 批量获取
r.mset(name="xixi", age=18)
r.mget("name", "age")
[b'xixi', b'18']
r.set("name", "koka")
getset(name, value)
# 设置新值并获取原来的值
r.getset("name", "akok")
b'koka'
r.get("name")
b'akok'
getrange(key, start, end)
# 获取子序列(根据字节获取,非字符)
# 参数:
# name,Redis 的 name
# start,起始位置(字节)
# end,结束位置(字节)
# 如: "武沛齐" ,0-2表示 "武"
r.set("parter", "柴少")
r.getrange("parter", 0, 2).decode()
'柴'
setrange(name, offset, value)
# 修改字符串内容,从指定字符串索引开始向后替换(新值太长时,则向后添加)
# 参数:
# offset,字符串的索引,字节(一个汉字三个字节)
# value,要设置的值 r.set("name", 'ok')
# 修改字符串内容,从指定字符串索引开始向后替换
r.setrange("name", 0, "ko")
r.get("name")
b'ko'
setbit(name, offset, value)
# 对name对应值的二进制表示的位进行操作 # 参数:
# name,redis的name
# offset,位的索引(将值变换成二进制后再进行索引)
# value,值只能是 1 或 0 ord('k') # 107
ord('o') # 111
# 107 => 0 1 1 0 1 0 1 1
# 111 => 0 1 1 0 1 1 1 1
r.setbit("name", 7, 0)
# 0 1 1 0 1 0 1 1 => 0 1 1 0 1 0 1 0 106 => j
r.get("name")
b'jo'
r.setbit("name", 15, 0)
# 0 1 1 0 1 1 1 1 => 0 1 1 0 1 1 1 0 110 => n
r.get("name")
b'jn'
getbit(name, offset)
# 获取name对应的值的二进制表示中的某位的值 (0或1)
bin(ord('j')).replace('b', '')
'01101010'
bin(ord('n')).replace('b', '')
'01101110'
r.set("name", "jn")
r.getbit("name", "2")
1
bitcount(key, start=None, end=None)
# 获取name对应的值的二进制表示中 1 的个数
# 参数:
# key,Redis的name
# start,位起始位置
# end,位结束位置
r.bitcount("name", 0, 1)
9
str(bin(ord('j')) + bin(ord('n'))).replace('b', '').count("1")
9
incr(self, name, amount=1)
# 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。 # 参数:
# name,Redis的name
# amount,自增数(必须是整数) # 注:同incrby r.set('n', 1)
r.incr("n", '3')
4
incrbyfloat(self, name, amount=1.0)
# 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。 # 参数:
# name,Redis的name
# amount,自增数(浮点型) r.incrbyfloat('n', 1)
3.0
decr(self, name, amount=1)
# 自减 name对应的值,当name不存在时,则创建name=amount,否则,则自减。 # 参数:
# name,Redis的name
# amount,自减数(整数) r.set('n', '2')
r.decr('n', 1)
1
append(key, value)
# 在redis name对应的值后面追加内容 # 参数:
key, redis的name
value, 要追加的字符串
r.append('n', 'a')
2
r.get("n")
b'1a'
Hash操作,redis中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时则创建(相当于添加) r.hset("h1", "name", "koka")
1
r.hget("h1", "name")
b'koka'
hmset(name, mapping)
# 在name对应的hash中批量设置键值对 # 参数:
# name,redis的name
# mapping,字典,如:{'k1':'v1', 'k2': 'v2'} # 如:
# r.hmset('xx', {'k1':'v1', 'k2': 'v2'}) r.hmset('n1', {'k1': 'v1', 'k2': 'v2'})
r.hmget("n1", "k1", "k2")
[b'v1', b'v2']
hgetall(name)
# 获取name对应hash的所有键值
r.hgetall("n1")
{b'k2': b'v2', b'k1': b'v1'}
hlen(name)
# 获取name对应的hash中键值对的个数
r.hlen("n1")
2
hkeys(name)
# 获取name对应的hash中所有的key的值
r.hkeys("n1")
[b'k2', b'k1']
hvals(name)
# 获取name对应的hash中所有的value的值
r.hvals("n1")
[b'v2', b'v1']
hexists(name, key)
# 检查name对应的hash是否存在当前传入的key
r.hexists("n1", "k1")
hdel(name,*keys)
# 将name对应的hash中指定key的键值对删除
r.hdel("n1", "k1")
1
hincrby(name, key, amount=1)
# 自增name对应的hash中的指定key的值,不存在则创建key=amount
# 参数:
# name,redis中的name
# key, hash对应的key
# amount,自增数(整数) r.hincrby("n1", "k1", 1)
1
hincrbyfloat(name, key, amount=1.0)
# 自增name对应的hash中的指定key的值,不存在则创建key=amount # 参数:
# name,redis中的name
# key, hash对应的key
# amount,自增数(浮点数) # 自增name对应的hash中的指定key的值,不存在则创建key=amount r.hincrbyfloat("n1", "k1", 1)
2.0
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时,表示数据已经通过分片获取完毕 r.hscan("n1")
(0, {b'k2': b'v2', b'k1': b'3'})
hscan_iter(name, match=None, count=None)
# 利用yield封装hscan创建生成器,实现分批去redis中获取数据 # 参数:
# match,匹配指定key,默认None 表示所有的key
# count,每次分片最少获取个数,默认None表示采用Redis的默认分片个数 for i in r.hscan_iter("n1", match=None, count=None):print(i)
(b'k2', b'v2')
(b'k1', b'3')
List操作,redis中的List在在内存中按照一个name对应一个List来存储。如图:
lpush(name,values)
# 在name对应的list中添加元素,每个新的元素都添加到列表的最左边 # 如:
# r.lpush('oo', 11,22,33)
# 保存顺序为: 33,22,11 # 扩展:
# rpush(name, values) 表示从右向左操作 r.lpush("l1", [11, 22, 33, 44])
1
r.lpush("l1", [11, 22, 33, 44])
2
r.lrange("l1", '0', '3')
[b'[11, 22, 33, 44]', b'[11, 22, 33, 44]']
r.lpush("l3", "AA", "BB", "CC", "DD")
1
r.lrange("l3",0,2)
[b'CC', b'BB', b'AA']
lpushx(name,value)
# 在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边 # 更多:
# rpushx(name, value) 表示从右向左操作 r.lpushx("l2", "33")
0
r.lrange("l2",0,1)
[]
llen(name)
# name对应的list元素的个数
r.llen("l1")
2
linsert(name, where, refvalue, value))
# 在name对应的列表的某一个值前或后插入一个新值 # 参数:
# name,redis的name
# where,BEFORE或AFTER
# refvalue,标杆值,即:在它前后插入数据
# value,要插入的数据 r.lpush("l3", "AA", "BB", "CC", "DD")
r.lrange("l3", 0, 2)
[b'CC', b'BB', b'AA'] r.linsert("l3", "AFTER", "CC", "cc")
r.lrange("l3", 0, 3)
[b'CC', b'cc', b'BB', b'AA']
r.lset(name, index, value)
# 对name对应的list中的某一个索引位置重新赋值 # 参数:
# name,redis的name
# index,list的索引位置
# value,要设置的值 r.lset("l3", '2', 'Cc')
r.lrange("l3", '0', '5')
[b'DD', b'CC', b'Cc', b'BB', b'AA']
r.lrem(name, value, num)
# 在name对应的list中删除指定的值 # 参数:
# name,redis的name
# value,要删除的值
# num, num=0,删除列表中所有的指定值;
# num=2,从前到后,删除2个;
# num=-2,从后向前,删除2个 r.lrem("l3", 'Cc')
1
r.lrange("l3", '0', '4')
[b'DD', b'CC', b'BB', b'AA']
lpop(name)
# 在name对应的列表的左侧获取第一个元素并在列表中移除,返回值则是第一个元素
# 更多:
# rpop(name) 表示从右向左操作
r.lpop("l3")
b'DD'
r.lrange("l3", '0', '2')
[b'CC', b'BB', b'AA']
ltrim(name, start, end)
# 在name对应的列表中移除没有在start-end索引之间的值
# 参数:
# name,redis的name
# start,索引的起始位置
# end,索引结束位置 r.ltrim("l3", "0", "1")
True
r.lrange("l3", '0', '3')
[b'CC', b'BB']
rpoplpush(src, dst)
# 从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边
# 参数:
# src,要取数据的列表的name
# dst,要添加数据的列表的name
r.lpush("l4", '11', '22', '33')
r.lpush("l5", '44', '55', '66')
r.rpoplpush("l4", "l5")
b'11'
r.lrange("l4", '0', '3')
[b'33', b'22']
r.lrange("l5", '0', '3')
[b'11', b'66', b'55', b'44']
blpop(keys, timeout)
# 将多个列表排列,按照从左到右去pop对应列表的元素 # 参数:
# keys,redis的name的集合
# timeout,超时时间,当元素所有列表的元素获取完之后,阻塞等待列表内有数据的时间(秒), 0 表示永远阻塞 # 更多:
# r.brpop(keys, timeout),从右向左获取数据 r.blpop("l5", timeout=1)
(b'l5', b'11')
r.lrange("l5",0,3)
[b'66', b'55', b'44']
lindex(name, index)
#在name对应的列表中根据索引获取列表元素
>>> r.lrange("l3",0,3)
[b'CC', b'cc', b'BB', b'AA']
>>> r.lindex("l3","0")
b'CC'
自定义增量迭代
# 由于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 range(list_count):
yield r.lindex(name, index) # 使用
for item in list_iter('l3'):
print(item)
Set操作,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 对应的分数
r.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,用来对分数进行操作
其他常用操作
delete(*names)
# 根据删除redis中的任意数据类型
r.set("test","123")
r.get('test')
b'123'
r.delete("test")
1
r.get("test")
None
exists(name)
# 根据删除redis中的任意数据类型
r.set("test","123")
r.get('test')
b'123'
r.delete("test")
1
r.exists("test")
False
keys(pattern='*')
# 根据模型获取redis的name # 更多:
# KEYS * 匹配数据库中所有 key 。
# KEYS h?llo 匹配 hello , hallo 和 hxllo 等。
# KEYS h*llo 匹配 hllo 和 heeeeello 等。
# KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo r.keys(pattern="*")
[b'l5', b'parter', b'name', b'l3', b'l4', b'foo']
expire(name ,time)
# 为某个redis的某个name设置超时时间
r.set("t","ok")
r.expire("t",3)
r.get("t") # 隔3秒后取值
None
rename(src, dst)
# 对redis的name重命名为
r.set('rn','123')
r.rename('rn','rename')
r.get('rename')
b'123'
move(name, db))
# 将redis的某个值移动到指定的db下
randomkey()
# 随机获取一个redis的name(不删除)
type(name)
# 获取name对应值的类型
r.get("name")
b'jn'
r.type("name")
b'string'
scan(cursor=0, match=None, count=None)
scan_iter(match=None, count=None)
# 同字符串操作,用于增量迭代获取key
4、管道
redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作。
#!/usr/bin/env python
# -*- coding:utf-8 -*- import redis pool = redis.ConnectionPool(host='10.211.55.4', port=6379) r = redis.Redis(connection_pool=pool) # pipe = r.pipeline(transaction=False)
pipe = r.pipeline(transaction=True) r.set('username', 'koka')
r.set('passwd', '123') pipe.execute()
5、发布订阅
发布者:服务器
订阅者:Dashboad和数据处理
Demo如下:
订阅者:
# !/usr/bin/env python
# -*- coding:utf-8 -*- from monitor.RedisHelper import RedisHelper obj = RedisHelper()
redis_sub = obj.subscribe() while True:
msg= redis_sub.parse_response()
print(msg)
发布者:
#!/usr/bin/env python
# -*- coding:utf-8 -*- from monitor.RedisHelper import RedisHelper obj = RedisHelper()
obj.public('hello')
redis setnx 方法: 在指定的 key不存在时,为 key 设置指定的值;存在设置失败;
设置成功 1 失败: 0
更多参见:
https://github.com/andymccurdy/redis-py/
http://doc.redisfans.com/
http://www.cnblogs.com/wupeiqi/articles/5132791.html
Python + redis操作Redis数据库的更多相关文章
- [转]使用python来操作redis用法详解
转自:使用python来操作redis用法详解 class CommRedisBase(): def __init__(self): REDIS_CONF = {} connection_pool = ...
- Redis操作,数据库操作
Redis操作,数据库操作 案例1:源码安装Redis缓存服务 案例2:常用Redis数据库操作指令 案例3:配置Redis主从服务器 1 案例1:源码安装Redis缓存服务 1.1 问题 本案例要求 ...
- 使用Spring Data Redis操作Redis(集群版)
说明:请注意Spring Data Redis的版本以及Spring的版本!最新版本的Spring Data Redis已经去除Jedis的依赖包,需要自行引入,这个是个坑点.并且会与一些低版本的Sp ...
- Python之操作redis数据库
使用redis模块 一.操作redis 1.添加信息 (1)直接建key-value信息: 右键-Add New Key,手动添加key和value 右键-Console,打开控制台,写入命令 (2) ...
- Python【操作Redis数据库】
Redis非关系型数据库,数据存放在计算机内存中,无SQL语句.Redis中有多种数据类型,比较常用的数据类型是string类型和hash类型.平时我们使用RedisDesktopManager来对R ...
- Python之操作Redis、 RabbitMQ、SQLAlchemy、paramiko、mysql
一.Redis Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.Redis是一个key-value存储系统.和 ...
- 使用python来操作redis用法详解
1.redis连接 redis提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令,Redis是StrictRe ...
- 用Python来操作redis 以及在Django中使用redis
什么是Redis? Redis是一款开源的.高性能的键-值存储(key-value store).它常被称作是一款数据结构服务器(data structure server). Redis的键值可以包 ...
- Python中操作Redis
一 Rdis基本介绍 redis是一个key-value存储系统.它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set -- ...
- redis的安装使用以及在python中操作redis
一.Redis介绍: Redis可以看作是一个key-value的存储系统,它为我们提供了丰富的数据结构,包括lists,sets,ordered sets和hashes.还包括了对这些数据结构的丰富 ...
随机推荐
- 【SQL】将日期时间转换成年月日的日期形式
[SQL]将日期时间转换成年月日的日期形式 这段时间写力扣的SQL题,发现了各式各样的转换时间的方法,正好记录一下 TO_CHAR(XXX,'YYYY-MM-DD') 这个在Oracle应该是很常用的 ...
- 力扣122(java&python)-买卖股票的最佳时机 II(中等)
题目: 给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格. 在每一天,你可以决定是否购买和/或出售股票.你在任何时候 最多 只能持有 一股 股票.你也可以先购买 ...
- 力扣168(java)-Excel表列名称(简单)
题目: 给你一个整数 columnNumber ,返回它在 Excel 表中相对应的列名称. 例如: A -> 1B -> 2C -> 3...Z -> 26AA -> ...
- 重新定义容器化 Serverless 应用的数据访问
简介: 本文首先聚焦到 AI 和大数据等应用 Serverless 化的最大挑战:计算和存储分离架构带来的数据访问延迟和远程拉取数据带宽巨大的挑战.尤其在 GPU 深度学习训练场景中,迭代式的远程读取 ...
- 【产品动态】一文详细解读智能数据构建产品Dataphin的“规划”功能
简介: 数据中台是传统的数据仓库的一种升级, 是数据采集.建设.管理与使用的一整套体系,Dataphin是一个构建数据中台的强大工具, 核心优势是在数据的建设与管理上引入了阿里巴巴多年来数据中台建设 ...
- [GPT] 对于一个复杂的html文档而言,如何用 js 批量替换页面上的某些文字从A替换为B,前提是不能去掉标签和已绑定的事件
原生:示例代码 function replaceTextInDocument(node) { if (node.nodeType === Node.TEXT_NODE) { node.textCo ...
- dotnet C# 多次对一个对象调用构造函数会发生什么
今天来玩一点变态的,使用反射获取到某个类型的构造函数,接着多次对此类型的某个对象调用构造函数方法.请问此时会发生什么 假定有一个类型 Foo 的定义如下 class Foo : IDisposable ...
- Pod进阶篇:污点-容忍度-亲和性-Affinity-调度(5)
一.Pod资源清单详细解读 apiVersion: v1 #版本号,例如 v1 kind: Pod #资源类型,如 Pod metadata: #元数据 name: string # Pod 名字 n ...
- RK 平台安装 ubuntu 系统
一.简介 之前有介绍到 ARM 平台移植 ubuntu 的操作流程,在 RK 系列的平台同样适用,所以这里就不介绍怎么一步步的去对 ubuntu 进行移植,而是怎么将移植的过程编写成脚本,这样便可以在 ...
- Solution Set - LCT
A[洛谷P3690]维护一个森林,支持询问路径xor和,连边(已连通则忽略),删边(无边则忽略),改变点权. B[洛谷P3203]\(n\)个装置编号为\(0,...,n-1\),从\(i\)可以一步 ...