Redis的基础使用

Redis介绍

  • 特点及优点
python 复制代码
1、开源的,使用C编写,基于内存且支持持久化
2、高性能的Key-Value的NoSQL数据库
3、支持数据类型丰富,字符串strings,散列hashes,列表lists,集合sets,有序集合sorted sets 等等
4、支持多种编程语言(C C++ Python Java PHP ... )
5、单进程单线程
  • 与其他数据库对比
python 复制代码
1、MySQL : 关系型数据库,表格,基于磁盘,慢
2、MongoDB:键值对文档型数据库,值为类似JSON文档,数据结构相对单一
3、Redis的诞生是为了解决什么问题??
   # 解决硬盘IO带来的性能瓶颈
  • 应用场景
python 复制代码
1,缓存
2,并发计数
3,排行榜
4,生产者消费者模型
...
  • redis版本
python 复制代码
1、最新版本:5.0
2、常用版本:2.4、2.6、2.8、3.0(里程碑)、3.2、3.4、4.0(教学环境版本)、5.0
  • Redis附加功能
python 复制代码
1、持久化
  将内存中数据保存到磁盘中,保证数据安全,方便进行数据备份和恢复
2、过期键功能
   为键设置一个过期时间,让它在指定时间内自动删除
   <节省内存空间>
   # 音乐播放器,日播放排名,过期自动删除
3、事务功能
   原子的执行多个操作
4、主从复制
5、Sentinel哨兵

安装

  • Ubuntu
python 复制代码
# 安装
sudo apt-get install redis-server
# 服务端启动
sudo /etc/init.d/redis-server status | start | stop | restart
# 客户端连接
redis-cli -h IP地址 -p 6379 -a 密码

配置文件详解

  • 配置文件所在路径
python 复制代码
/etc/redis/redis.conf
mysql的配置文件在哪里? : /etc/mysql/mysql.conf.d/mysqld.cnf
  • 设置连接密码
python 复制代码
1、requirepass 密码
2、重启服务
   sudo /etc/init.d/redis-server restart
3、客户端连接
   redis-cli -h 127.0.0.1 -p 6379 -a 123456
   127.0.0.1:6379>ping
  • 允许远程连接
python 复制代码
1、注释掉本地IP地址绑定
  69行: # bind 127.0.0.1 ::1
2、关闭保护模式(把yes改为no)
  88行: protected-mode no
3、重启服务
  sudo /etc/init.d/redis-server restart
  • 通用命令 适用于所有数据类型
python 复制代码
# 切换库(number的值在0-15之间,db0 ~ db15)
select number
# 查看键
keys 表达式  # keys *
# 数据类型
type key
# 键是否存在
exists key
# 删除键
del key
# 键重命名
rename key newkey
# 清除当前库中所有数据(慎用)
flushdb
# 清除所有库中所有数据(慎用)
flushall

数据类型

字符串类型(string)

  • 特点
python 复制代码
1、字符串、数字,都会转为字符串来存储
2、以二进制的方式存储在内存中
  • 字符串常用命令-必须掌握
python 复制代码
# 1. 设置一个key-value
set key value
# 2. 获取key的值
get key
# 3. key不存在时再进行设置(nx)
set key value nx  # not exists
# 4. 设置过期时间(ex)
set key value ex seconds

# 5. 同时设置多个key-value
mset key1 value1 key2 value2 key3 value3
# 6. 同时获取多个key-value
mget key1 key2 key3 
  • 字符串常用命令
python 复制代码
# 1.获取长度
strlen key
# 2.获取指定范围切片内容 [包含start stop]
getrange key start stop
# 3.从索引值开始,value替换原内容
setrange key index value
  • 数值操作
python 复制代码
# 整数操作
incrby key 步长
decrby key 步长
incr key : +1操作
decr key : -1操作
# 应用场景: 抖音上有人关注你了,是不是可以用INCR呢,如果取消关注了是不是可以用DECR
# 浮点数操作: 自动先转为数字类型,然后再进行相加减,不能使用append
incrbyfloat key step
  • string命令汇总
python 复制代码
# 字符串操作
1、set key value
2、set key value nx
3、get key
3、mset key1 value1 key2 value2
4、mget key1 key2 key3
5、set key value nx ex seconds
6、strlen key 
# 返回旧值并设置新值(如果键不存在,就创建并赋值)
7、getset key value
# 数字操作
7、incrby key 步长
8、decrby key 步长
9、incr key
10、decr key
11、incrbyfloat key number#(可为正数或负数)

# 设置过期时间的两种方式
# 方式一
1、set key value ex 3
# 方式二
1、set key value
2、expire key 5 # 秒
3、pexpire key 5 # 毫秒
# 查看存活时间
ttl key
# 删除过期
persist key
  • string数据类型注意
python 复制代码
# key命名规范
可采用 - wang:email
# key命名原则
1、key值不宜过长,消耗内存,且在数据中查找这类键值的计算成本高
2、不宜过短,可读性较差
# 值
1、一个字符串类型的值最多能存储512M内容
  • 业务场景
    • 缓存
      • 将mysql中的数据存储到redis字符串类型中
    • 并发计数 - 点赞/秒杀
      • 说明:通过redis单进程单线程的特点,由redis负责计数,并发问题转为串行问题
    • 带有效期的验证码 - 短信验证码
      • 借助过期时间,存放验证码;到期后,自动消亡

万个思考之后,清除所有库

### **列表数据类型(List)**

- **特点**

```python
1、元素是字符串类型
2、列表头尾增删快,中间增删慢,增删元素是常态
3、元素可重复
4、最多可包含2^32 -1个元素
5、索引同python列表
  • 列表常用命令
python 复制代码
# 增
1、从列表头部压入元素
	LPUSH key value1 value2 
    返回:list长度
2、从列表尾部压入元素
	RPUSH key value1 value2
    返回:list长度
3、从列表src尾部弹出1个元素,压入到列表dst的头部
	RPOPLPUSH src dst
    返回:被弹出的元素
4、在列表指定元素后/前插入元素
	LINSERT key after|before value newvalue
    返回:
		1,如果命令执行成功,返回列表的长度
		2,如果没有找到 pivot ,返回 -1
		3,如果 key 不存在或为空列表,返回 0 

# 查
5、查看列表中元素
	LRANGE key start stop
  # 查看列表中所有元素: LRANGE key 0 -1
6、获取列表长度
	LLEN key

# 删
7、从列表头部弹出1个元素
	LPOP key
8、从列表尾部弹出1个元素
	RPOP key
9、列表头部,阻塞弹出,列表为空时阻塞
	BLPOP key timeout
10、列表尾部,阻塞弹出,列表为空时阻塞
	BRPOP key timeout
  # 关于BLPOP 和 BRPOP
  	1、如果弹出的列表不存在或者为空,就会阻塞
	2、超时时间设置为0,就是永久阻塞,直到有数据可以弹出
	3、如果多个客户端阻塞再同一个列表上,使用First In First Service原则,先到先服务
11、删除指定元素
	LREM key count value
    count>0:表示从头部开始向表尾搜索,移除与value相等的元素,数量为count
	count<0:表示从尾部开始向表头搜索,移除与value相等的元素,数量为count
	count=0:移除表中所有与value相等的值
    返回:被移除元素的数量
    
12、保留指定范围内的元素
	LTRIM key start stop
    返回:ok
    样例:
  		LTRIM mylist1 0 2 # 只保留前3条
  		# 应用场景: 保存微博评论最后500条
  		LTRIM weibo:comments 0 499
	# 改
13、将列表 key 下标为 index 的元素的值设置为 value
	LSET key index newvalue

python交互redis

  • 模块(redis)

Ubuntu

python 复制代码
sudo pip3 install redis
  • 使用流程
python 复制代码
import redis
# 创建数据库连接对象
r = redis.Redis(host='127.0.0.1',port=6379,db=0,password='123456')
  • 代码示例
python 复制代码
import redis

# 1 创建redis数据库连接对象
r = redis.Redis(password='123456')
# 2 使用,很多命令的返回值是字节串,需要用字符串
#  表示时,调用decode方法.
# 3.1 通用命令...
print(r.keys('*'))
print(r.exists('name'))
# 3.2 字符串类型的操作
r.set('uname', 'aid2102', 60)
print(r.get('uname').decode())
r.mset({'a': 100, 'b': 200, 'c': 300})
print(r.mget(['a', 'b', 'c']))
# 3.3 列表类型的操作
r.lpush('pylk1',100,200,300)
print(r.lrange('pylk1',0,-1))

list案例: 一个进程负责生产任务,一个进程负责消费任务

进程1: 生产者,product.py

python 复制代码
import redis
# 1 创建redis数据库连接对象
r = redis.Redis(password='123456')
# 2.向任务队列中添加任务,使用列表类型
# 任务格式: 任务类别_发送者_接收者_内容
task = 'sendMail_aid2102_mzg_helloworld'
r.lpush('lst:tasks',task)

进程2: 消费者,consumer.py

python 复制代码
import redis

r = redis.Redis(password='123456')

while True:
    task = r.brpop('lst:tasks',3)
    if task:
        print(task)
        # (b'lst:tasks', b'sendMail_aid2102_mzg_helloworld')
        # 处理任务
        task_data = task[1].decode()
        print(task_data)
        # sendMail_aid2102_mzg_helloworld
        lst_data = task_data.split('_')
        if lst_data[0] == 'sendMail':
            print('执行发送邮件的任务...')
    else:
        print('-no task!-')

位图操作bitmap

定义

python 复制代码
1、位图不是真正的数据类型,它是定义在字符串类型中
2、一个字符串类型的值最多能存储512M字节的内容,位上限:2^32
# 1MB = 1024KB
# 1KB = 1024Byte(字节)
# 1Byte = 8bit(位)

强势点

python 复制代码
可以实时的进行统计,极其节省空间。官方在模拟1亿2千8百万用户的模拟环境下,在一台MacBookPro上,典型的统计如"日用户数"的时间消耗小于50ms, 占用16MB内存

SETBIT 命令

  • 说明:设置某位置上的二进制值

  • 语法:SETBIT key offset value

  • 参数:offset - 偏移量 从0开始

    ​ value - 0或者1

  • 示例:

python 复制代码
# 默认扩展位以0填充
127.0.0.1:6379> SET mykey ab
OK
127.0.0.1:6379> GET mykey
"ab"
127.0.0.1:6379> SETBIT mykey 0 1
(integer) 0
127.0.0.1:6379> GET mykey
"\xe1b"
127.0.0.1:6379> SETBIT mykey 17 1
"\xe1b@"

如果要设置的位偏移量过大默认会按照最小字节对内容进行扩展 使用0000 0000 填充然后进行操作

GETBIT 命令

  • 说明:获取某一位上的值

  • 语法:GETBIT key offset

  • 示例:

python 复制代码
127.0.0.1:6379> GETBIT mykey 3
(integer) 0
127.0.0.1:6379> GETBIT mykey 0
(integer) 1
127.0.0.1:6379> 

BITCOUNT 命令

  • 说明:统计键所对应的值中有多少个 1
  • 语法:BITCOUNT key start end
  • 参数:start/end 代表的是 字节索引
  • 示例:
python 复制代码
127.0.0.1:6379> SET mykey1 ab
OK
127.0.0.1:6379[4]> BITCOUNT mykey
(integer) 6
127.0.0.1:6379[4]> BITCOUNT mykey 0 0
(integer) 3

应用场景案例

python 复制代码
# 网站用户的上线次数统计(寻找活跃用户)
	用户名为key,上线的天作为offset,上线设置为1
# 示例
	用户名为 user1:login 的用户,今年第1天上线,第30天上线
	SETBIT user1:login 0 1 
	SETBIT user1:login 29 1
	BITCOUNT user1:login

Hash散列数据类型

  • 定义
python 复制代码
1、由field和关联的value组成的键值对
2、field和value是字符串类型
3、一个hash中最多包含2^32-1个键值对
  • 优点
python 复制代码
1、节约内存空间 - 特定条件下 【1,字段小于512个,2:value不能超过64字节】
2、可按需获取字段的值
  • 缺点(不适合hash情况)
python 复制代码
1,使用过期键功能:键过期功能只能对键进行过期操作,而不能对散列的字段进行过期操作
2,存储消耗大于字符串结构
  • 基本命令操作
python 复制代码
# 1、设置单个字段
HSET key field value
HSETNX key field value
# 2、设置多个字段
HMSET key field value field value
# 3、返回字段个数
HLEN key
# 4、判断字段是否存在(不存在返回0)
HEXISTS key field
# 5、返回字段值
HGET key field
# 6、返回多个字段值
HMGET key field filed
# 7、返回所有的键值对
HGETALL key
# 8、返回所有字段名
HKEYS key
# 9、返回所有值
HVALS key
# 10、删除指定字段
HDEL key field 
# 11、在字段对应值上进行整数增量运算
HINCRBY key field increment
# 12、在字段对应值上进行浮点数增量运算
HINCRBYFLOAT key field increment

python操作hash

python 复制代码
# 1、更新一条数据的属性,没有则新建
hset(name, key, value) 
# 2、读取这条数据的指定属性, 返回字符串类型
hget(name, key)
# 3、批量更新数据(没有则新建)属性,参数为字典
hmset(name, mapping)
# 4、批量读取数据(没有则新建)属性
hmget(name, keys)
# 5、获取这条数据的所有属性和对应的值,返回字典类型
hgetall(name)
# 6、获取这条数据的所有属性名,返回列表类型
hkeys(name)
# 7、删除这条数据的指定属性
hdel(name, *keys)

应用场景:用户维度数据统计

python 复制代码
用户维度统计
   统计数包括:关注数、粉丝数、喜欢商品数、发帖数
   用户为key,不同维度为field,value为统计数
   比如关注了5人
	 HSET user:10000 fans 5
	 HINCRBY user:10000 fans 1

python操作hash

import redis

# 创建redis数据库的连接对象
r = redis.Redis(password='123456')

# 操作hash
r.hset('pyhk1', 'username', 'aid2102')
r.hmset('pyhk1', {'age': 18, 'major': 'python'})
print(r.hget('pyhk1', 'username').decode())
print(r.hmget('pyhk1', ['username', 'age']))
print(r.hgetall('pyhk1'))
# 字典推导式
data = {k.decode(): v.decode() for k, v in r.hgetall('pyhk1').items()}
print(data)
r.hdel('pyhk1','age')
print(r.hgetall('pyhk1'))
# 删除键
r.delete('pyhk1')

集合数据类型(set)

  • 特点
python 复制代码
1、无序、去重
2、元素是字符串类型
3、最多包含2^32-1个元素
  • 基本命令
python 复制代码
# 1、增加一个或者多个元素,自动去重;返回值为成功插入到集合的元素个数
SADD key member1 member2
# 2、查看集合中所有元素
SMEMBERS key
# 3、删除一个或者多个元素,元素不存在自动忽略
SREM key member1 member2
# 4、元素是否存在
SISMEMBER key member
# 5、随机返回集合中指定个数的元素,默认为1个
SRANDMEMBER key [count]
# 6、弹出成员
SPOP key [count]
# 7、返回集合中元素的个数,不会遍历整个集合,只是存储在键当中了
SCARD key
# 8、把元素从源集合移动到目标集合
SMOVE source destination member

# 9、差集(number1 1 2 3 number2 1 2 4 结果为3)
SDIFF key1 key2 
# 10、差集保存到另一个集合中
SDIFFSTORE destination key1 key2

# 11、交集
SINTER key1 key2
SINTERSTORE destination key1 key2

# 11、并集
SUNION key1 key2
SUNIONSTORE destination key1 key2

案例: 新浪微博的共同关注

python 复制代码
# 需求: 当用户访问另一个用户的时候,会显示出两个用户共同关注过哪些相同的用户
# 设计: 将每个用户关注的用户放在集合中,求交集即可
# 实现:
	user001 = {'peiqi','qiaozhi','danni'}
	user002 = {'peiqi','qiaozhi','lingyang'}
  
user001和user002的共同关注为:
	SINTER user001 user002
	结果为: {'peiqi','qiaozhi'}

python操作set

import redis

r = redis.Redis(password='123456')
'''
   武将: 张飞 许褚 赵云 马超 周瑜
   文臣: 诸葛亮 周瑜 司马懿
   结果: 1.纯武将 2.纯文臣  3.文武双全  4.文臣武将
'''
# set集合类型的操作
r.sadd('武将', '张飞', '许褚', '赵云', '马超', '周瑜')
r.sadd('文臣', '诸葛亮', '周瑜', '司马懿')
data1 = r.sdiff('武将', '文臣')
result = []
for item in data1:
    result.append(item.decode())
print('纯武将:', result)

data2 = r.sdiff('文臣', '武将')
result = []
for item in data2:
    result.append(item.decode())
print('纯文臣:', result)

data3 = r.sinter('文臣', '武将')
result = []
for item in data3:
    result.append(item.decode())
print('文武双全:', result)

data4 = r.sunion('文臣', '武将')
result = []
for item in data4:
    result.append(item.decode())
print('文臣武将:', result)

有序集合sortedset

  • 特点

    1、有序、去重
    2、元素是字符串类型
    3、每个元素都关联着一个浮点数分值(score),并按照分值从小到大的顺序排列集合中的元素(分值可以相同)
    4、最多包含2^32-1元素

  • 示例

    一个保存了水果价格的有序集合

分值 2.0 4.0 6.0 8.0 10.0
元素 西瓜 葡萄 芒果 香蕉 苹果

一个保存了员工薪水的有序集合

分值 6000 8000 10000 12000
元素 lucy tom jim jack

一个保存了正在阅读某些技术书的人数

分值 300 400 555 666 777
元素 核心编程 阿凡提 本拉登 阿姆斯特朗 比尔盖茨
  • 有序集合常用命令
python 复制代码
# 在有序集合中添加一个成员 返回值为 成功插入到集合中的元素个数
zadd key score member
# 查看指定区间元素(升序)
zrange key start stop [withscores]
# 查看指定区间元素(降序)
zrevrange key start stop [withscores]
# 查看指定元素的分值
zscore key member

# 返回指定区间元素
# offset : 跳过多少个元素
# count : 返回几个
# 小括号 : 开区间  zrangebyscore fruits (2.0 8.0
zrangebyscore key min max [withscores] [limit offset count]
# 每页显示10个成员,显示第5页的成员信息: 
# limit 40 10
# MySQL: 每页显示10条记录,显示第5页的记录
# limit 40,10
# limit 2,3   显示: 第3 4 5条记录

# 删除成员
zrem key member
# 增加或者减少分值
zincrby key increment member
# 返回元素排名
zrank key member
# 返回元素逆序排名
zrevrank key member
# 删除指定区间内的元素
zremrangebyscore key min max
# 返回集合中元素个数
zcard key
# 返回指定范围中元素的个数
zcount key min max
zcount salary 6000 8000 
zcount salary (6000 8000# 6000<salary<=8000
zcount salary (6000 (8000#6000<salary<8000               
# 并集
zunionstore destination numkeys key [weights 权重值] [AGGREGATE SUM|MIN|MAX]
# zunionstore salary3 2 salary salary2 weights 1 0.5 AGGREGATE MAX
# 2代表集合数量,weights之后 权重1给salary,权重0.5给salary2集合,算完权重之后执行聚合AGGREGATE
                     
# 交集:和并集类似,只取相同的元素
zinterstore destination numkeys key1 key2 weights weight AGGREGATE SUM(默认)|MIN|MAX

python操作sorted set

python 复制代码
import redis

r = redis.Redis(password='123456')

# 有序集合类型的操作
r.zadd('pyzk1', {'tedu': 100, 'tedu2': 200})
print(r.zrange('pyzk1', 0, -1, withscores=True))
r.zadd('pyzk2', {'tedu2': 200, 'tedu3': 200})
# 并集运算
r.zunionstore('pyzk3',['pyzk1','pyzk2'],aggregate='sum')
print(r.zrange('pyzk3', 0, -1, withscores=True))
# 并集运算(带权重)
r.zunionstore('pyzk4',{'pyzk1':0.8,'pyzk2':0.2},
              aggregate='sum')
print(r.zrange('pyzk4', 0, -1, withscores=True))

五大数据类型及应用场景

类型 特点 使用场景
string 简单key-value类型,value可为字符串和数字 常规计数(微博数, 粉丝数等功能)
hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象 存储部分可能需要变更的数据(比如用户信息)
list 有序可重复列表 消息队列等
set 无序不可重复列表 存储并计算关系(如微博,关注人或粉丝存放在集合,可通过交集、并集、差集等操作实现如共同关注、共同喜好等功能)
sorted set 每个元素带有分值的集合 各种排行榜

事务

特点

python 复制代码
1. 单独的隔离操作:事务中的所有命令会被序列化、按顺序执行,在执行的过程中不会被其他客户端发送来的命令打断
2. 不保证原子性:redis中的一个事务中如果存在命令执行失败,那么其他命令依然会被执行,没有回滚机制

事务命令

python 复制代码
1、MULTI  # 开启事务          mysql   begin
2、命令1  # 执行命令          
3、命令2 ... ...
4、EXEC  # 提交到数据库执行    mysql   commit
4、DISCARD # 取消事务         mysql  'rollback'

使用步骤

python 复制代码
# 开启事务
127.0.0.1:6379> MULTI
OK
# 命令1入队列
127.0.0.1:6379> INCR n1
QUEUED
# 命令2入队列
127.0.0.1:6379> INCR n2
QUEUED
# 提交到数据库执行
127.0.0.1:6379> EXEC
1) (integer) 1
2) (integer) 1

事务中命令错误处理

python 复制代码
# 1、命令语法错误,命令入队失败,直接自动discard退出这个事务
  这个在命令在执行调用之前会发生错误。例如,这个命令可能有语法错误(错误的参数数量,错误的命令名)
  处理方案:语法错误则自动执行discard

案例:
127.0.0.1:6379[7]> MULTI
OK
127.0.0.1:6379[7]> get a
QUEUED
127.0.0.1:6379[7]> getsss a
(error) ERR unknown command 'getsss'
127.0.0.1:6379[7]> 
127.0.0.1:6379[7]> 
127.0.0.1:6379[7]> EXEC
(error) EXECABORT Transaction discarded because of previous errors.

# 2、命令语法没错,但类型操作有误,则事务执行调用之后失败,无法进行事务回滚
   我们执行了一个由于错误的value的key操作(例如对着String类型的value施行了List命令操作) 
   处理方案:发生在EXEC之后的是没有特殊方式去处理的:即使某些命令在事务中失败,其他命令都将会被执行。

案例
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set num 10
QUEUED
127.0.0.1:6379> LPOP num
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> get num
"10"
127.0.0.1:6379> 

思考为什么redis不支持回滚?

pipeline 流水线

定义:批量执行redis命令,减少通信io

注意:此为客户端技术

示例

python 复制代码
import redis
# 创建连接池并连接到redis
pool = redis.ConnectionPool(host = '127.0.0.1',db=0,port=6379)
r = redis.Redis(connection_pool=pool)

pipe = r.pipeline()
pipe.set('fans',50)
pipe.incr('fans')
pipe.incrby('fans',100)
pipe.execute()

性能对比

python 复制代码
# 创建连接池并连接到redis
pool = redis.ConnectionPool(host = '127.0.0.1',db=0,port=6379)
r = redis.Redis(connection_pool=pool)

def withpipeline(r):
    p = r.pipeline()
    for i in range(1000):
        key = 'test1' + str(i)
        value = i+1
        p.set(key, value)
    p.execute()

def withoutpipeline(r):
    for i in range(1000):
        key = 'test2' + str(i)
        value = i+1
        r.set(key, value)

python 操作 redis事务

python 复制代码
with r.pipeline(transaction=true) as pipe
    pipe.multi()
    pipe.incr("books")
    pipe.incr("books")
    values = pipe.execute()

watch - 乐观锁

作用: 事务过程中,可对指定key进行监听,命令提交时,若被监听key对应的值未被修改时,事务方可提交成功,否则失败

python 复制代码
> watch books
OK
> multi
OK
> incr books
QUEUED
> exec  # 事务执行失败
(nil)


watch之后,再开一个终端进入redis
> incr books  # 修改book值
(integer) 1

python操作watch

python 复制代码
#同时对一个账户进行操作, 当前余额 * 2
相关推荐
Ai 编码助手3 小时前
MySQL中distinct与group by之间的性能进行比较
数据库·mysql
陈燚_重生之又为程序员3 小时前
基于梧桐数据库的实时数据分析解决方案
数据库·数据挖掘·数据分析
caridle3 小时前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
白云如幻3 小时前
MySQL排序查询
数据库·mysql
萧鼎3 小时前
Python并发编程库:Asyncio的异步编程实战
开发语言·数据库·python·异步
^velpro^3 小时前
数据库连接池的创建
java·开发语言·数据库
荒川之神3 小时前
ORACLE _11G_R2_ASM 常用命令
数据库·oracle
IT培训中心-竺老师3 小时前
Oracle 23AI创建示例库
数据库·oracle
小白学大数据4 小时前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
time never ceases4 小时前
使用docker方式进行Oracle数据库的物理迁移(helowin/oracle_11g)
数据库·docker·oracle