redis基础操作介绍
NoSQL
NoSQL:NoSQL = Not Only SQL 非关系型数据库
NoSQL,泛指非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。
1.1 优点
- 高可扩展性
- 分布式计算
- 低成本
- 架构的灵活性,半结构化数据
- 没有复杂的关系
1.2 缺点
- 没有标准化
- 有限的查询功能(到目前为止)
redis
2.1简介:
- Remote Dictionary Server 缩写 是个基于内存的网络存储系统
- 丰富的数据结构(sets, sorted sets,hashes, list …)
- 本质是key-value,但是与memcached不同的是,value的类型得到了扩展
Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。
Redis 与其他 key - value 缓存产品有以下三个特点:
- Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
- Redis不仅仅支持简单的key-value string类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
- Redis支持数据的备份,即master-slave模式的数据备份。
2.2 安装
- 安装
sudo apt install redis-server - 查看运行情况
ps -aux |grep redis - 开启与重启服务
sudo service redis start | stop |restart - 端口
netstat -nlt|grep 6379
2.3运行,远程主机访问
2.3.1 进入客户端:
redis-cli
2.3.2 远程访问配置
进入/etc/redis/redis.conf 文件,需要修改权限,或者用sudo权限打开
bind 0.0.0.0::1 # 将这个改为0.0.0.0 ::1 ,原来默认是127.0.0.1::1
protected-node no # 将这个改为no , 原来默认是yes
sudo service redis restart #重启服务
redis-cli -h 10.0.102.67 -p 6379 # -h ip地址 -p 端口号
ps : redis中默认为0号数据库: select 0 默认
2.3 数据类型
== key - value的结构==
2.3.1 string 字符串
-
增加数据
set key value [ex seconds]
nx: 不存在则创建
xx: 存在则创建 -
获取值
get key 根据key得到value值 -
设置过期时间
setnx count 1
setex 设在过期时间单位seconds -
批量设置和取值:
mset key value key value …
mget key key key -
修改值
set count 99 -
设置新值取回旧值
getset key new_value --→ old value -
自增自减
增加 incr key —→ +1
减少 decr key —→ -1
incrby key 5 —→ 指定值增加
decrby key 5 —→ 指定值减少 -
其他常用操作
类似的切片: getrange key start end
getrange message 0 -1 —→ ‘helloworld’
setrange key offset value --→
setrange message 5 abc
getrange message 0 -1 ====> “helloabcld” -
字符串长度:
strlen key
2.3.2 hash 哈希
-
介绍
user :name
key 可以绑定一些关联性较强数据
user:{name:’’,password:’’,addr:’’,phone:’’} -
获取设置值
设置: hset key field value --→ 设置field-value到key
取值: hget key field 只能获取指定field的值 -
多个数据操作
hmset: HMSET key field value [field value …]
hmget: HMGET key field [field …] -
取:
hgetall key --→ dict.items()
hkeys key —→ dict.keys()
hvals key —→ dict.values() -
删除:
hdel key field —→ 根据field删除field-value -
获取个数:
hlen key
hexists key field
2.3.3 list 列表
- 增加
lpush key value value —>返回:长度 - 获取长度
llen key 获取列表长度 - 存在才增加
lpushx key value value 如果有key才会存alue - 内容
lrange key start end 获取列表内容 - 插入 before在参照之前
linsert key before 参照 new_value - 下标添加
lset key index new_value --→ 最后一个添加的元素是0 - 删除
lrem key count ele count表示个数(list是允许重复,就会有多个相同值,通过count指定个数)
lrem fruit 1 apple --→ 删除一个apple(最上面的)
lpop key --→ 删除list的第一个元素(最上面的元素) - 下标索引法
lindex key index —→ 根据下标获取对应的元素
2.3.4 set 集合
-
添加
sadd key number number
sadd citys beijing tianjin … -
长度:
scard key -
查看元素
smembers key -
交并集
交集: sinter key1 key2
差集: sdiff key1 key2
并集: sunion key1 key2
Redis Sinterstore 命令将给定集合之间的交集存储在指定的集合中。如果指定的集合已经存在,则将其覆盖。
sinterstore citys city1
redis 127.0.0.1:6379> SADD myset1 "hello"
(integer) 1
redis 127.0.0.1:6379> SADD myset1 "foo"
(integer) 1
redis 127.0.0.1:6379> SADD myset1 "bar"
(integer) 1
redis 127.0.0.1:6379> SADD myset2 "hello"
(integer) 1
redis 127.0.0.1:6379> SADD myset2 "world"
(integer) 1
redis 127.0.0.1:6379> SINTERSTORE myset myset1 myset2
(integer) 1
redis 127.0.0.1:6379> SMEMBERS myset
1) "hello
- 长度
scard key 获取set的长度
sismember key member --→ 判断member是否是key中成员 - 删除
smove 源 目标 member
spop key 随机删除元素
srem key member 指定元素删除 - 随机返回一个数据,原数据不变
srandmember key
2.3.5 sorted set 有序集合
- 介绍
有序集合,在集合的基础上,为每元素排序;元素的排序需要根据另外一个值来进行比较,所以,对于有序集合,每一个元素有两个值,即:值和分数,分数专门用来做排序。 - 使用场景
常用于排行榜,如视频网站需要对用户上传视频做排行榜,或点赞数 - 增加
zadd key [nx|xx] score member
zadd zan 100 james 200 tom --->按照score进行升序排列
zadd zan nx 600 james 不存在则创建
zadd zan xx 601 james 存在则修改了原来的score
zadd zan xx incr 1 james 如果存在则在原来的基础上增加1
- 指定范围取值:
zrange key start end withscores 升序
zrevrange key start end withscores 降序
zrangebyscore 根据score的值(min,max)获取member内容
zremrangebyscore key min max [WITHSCORES] [LIMIT offset count]
zrevrangebyscore 降序取member
zremrangebyscore key max min [WITHSCORES] [LIMIT offset count]
zrangebyscore zan (200 inf withscores ---→ 从200到inf无限制大
zrevrangebyscore zan (200 -inf withscores ---》小于200以下的所有值(无限)
-
删除:
zrem key member 删除指定member的元素 -
运算:交集 并集 差集
ZINTERSTORE destination numkeys key [key …] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
ZUNIONSTORE destination numkeys key [key …] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
2.4 redis的其他问题
key:
keys * 获取所有
keys a* 获取a开头的,后面有1个字母的
keys a??? 获取a开头,后面有多个字母的
del key 删除key
type key key的类型
rename key newkey 重命名某个key
expire key ex 10000 为某个key添加过期时间
flushdb 清空当前库所有key
flushall 清空所有库的key
pycharm连接redis
3.1 安装第三方库redis
pip install redis
3.2 连接redis
import redis
r = redis.StricRedis("localhost",6379,0)
# 第一个参数为ip地址,第二个端口号,第三个使用的数据库号
print(r) # 不报错则连接成功
3.3 pycharm与redis
- StricRedis 尽量坚持官方语法,除了以下命令:
• select 没有实现,考虑到了线程安全
• del Python 关键字,用 delete 代替
• config get|se 作为 config_get / config_set 实现
• multi / exec 作为 Pipeline 类的一部分实现的。 - Redis 类是 StricRedis 的子类,提供向后的兼容性。推荐使用 StricRedis。Redis 覆盖了几个命令:
• lrem num 和 value 参数顺序颠倒,num 提供默认值 0
• zadd Redis类期望* args的形式为:name1,score1,name2,score2,…,而 StricRedis 是 score1,name1,score2,name2,…,这与 Redis 一样。
setex time 和 value 顺序颠倒。在 Redis 类中是:setex(key, value, time),在 StricRedis 类中是:setex(key, time, value)。
3.4 连接优化问题
大多数情况下,我们都会通过请求-相应机制去操作redis。只用这种模式的一般的步骤是,先获得redis实例,然后通过redis的get/set方法与redis交互。由于redis是单线程的,下一次请求必须等待上一次请求执行完成后才能继续执行。然而使用Pipeline模式,客户端可以一次性的发送多个命令,无需等待服务端返回。这样就大大的减少了网络往返时间,提高了系统性能。
import redis
r = redis.StricRedis("localhost",6379,0)
# 第一个参数为ip地址,第二个端口号,第三个使用的数据库号
print(r) # 不报错则连接成功
pip = r.pipeline() # 使用pipline优化
3.5 小案例
案例: 每个用户有多个订单key为:
order:1 --->key
order:2
order:3,
结合hmset
hmset order:1 orderId 1 money 99.6 time 2019-08-31{}
hmset order:2 orderId 2 money 138.6 time 2019-08-31{}
hmset order:3 orderId 3 money 39.6 time 2019-08-31{}
把订单信息的key放到队列list
lpush user:1 order order:1 order:2 order:3 [{},{},{}]
每新产生一个订单,
hmset order:4 orderId 4 money 40.6 time 2019-08-31
追加一个order:4放入队列第一个位置
lpush user:1:order order:4
当需要查询用户订单记录时:
List orderKeys = lrange user:1 0 -1 //查询user:1 的所有订单key值
for(Order order: orderKeys){
hmget order:1
}
import redis
import uuid
from datetime import datetime
r = redis.StrictRedis(host='localhost', port=6379, db=0)
pip = r.pipeline()
username = input('输入用户名:')
# for i in range(1,4):
# orderid = str(uuid.uuid4()).replace('-', '')
# # print(orderid)
# money = input('订单金额:')
# time = datetime.now()
# # print(type(time))
# order_key = 'order:'+str(i)
# pip.hmset(order_key, {'orderid': orderid, 'money': money, 'time': str(time)})
#
# pip.lpush(username,'order:1','order:2','order:3')
# pip.execute()
order_all = r.lrange(username, 0, -1)
print(order_all)
for order in order_all:
result = r.hgetall(order)
# print(result)
# sql = 'insert into order(orderid,money,time) values(%s,%s,%s)'
# db.insert(sql, (result.get('orderid')))
print(result.get(b'orderid'))
print(result.get(b'money'))
print(result.get(b'time'))