redis操作
redis 版本迭代之后,存入的数据类型,再取出来就都是bytes类型了。需要转换一下。
本文转载自wusir博客点击进入
redis 删除多个key 示例 hmset key {"k1": "a", "k2": "b"} del key k*
这里直接用k*类似于模糊查询的方法即可实现多个相关的key同时删除,如果不能用模糊查询的话,我们也可以一一列举进行删除
del key k1,k2
示例:

1 import redis 2 3 # conn=redis.Redis(host='192.168.12.79',port=6379) 4 conn = redis.Redis(host='127.0.0.1', port=6379) 5 # conn.set('qqx','wahaha') 6 # val=conn.get('qqx') 7 # print(val) 8 # conn.hset('obj','name','wusir') 9 # print(conn.hget('obj','name')) 10 # conn.hmset('dic',{'a':'a1','b':'b1','c':'c1'}) # hmset是设置多个值, 11 # print(conn.hget('dic','a')) # 'a1' 12 # print(conn.hget('dic','b')) # 'b1' 13 # print(conn.hmget('dic','a','c')) # hmget是获取多个值 [b'a1', b'b1', b'c1'] 14 # print(conn.hgetall('dic')) # 取出所有键值对 {b'a': b'a1', b'b': b'b1', b'c': b'c1'} 15 # print(conn.hlen('dic')) # 取出长度,3 16 # print(conn.hkeys('dic')) # [b'a', b'b', b'c'] 17 # print(conn.hvals('dic')) # [b'a1', b'b1', b'c1'] 18 # print(conn.hexists('dic','wah')) # 返回bool值 19 # print(conn.hdel('dic','a','b')) 20 # print(conn.hexists('dic','a')) 21 # conn.hincrby('dic1','a',amount=2) # 这里是设置了自增2,每一次取值都是从里面取到前一次取出的值+2 22 # print(conn.hget('dic1', 'a')) # 每一次都执行这一句代码都是在上一次基础上+2 23 # print(conn.hdel('dic1','a')) 24 # conn.hincrbyfloat('dic0','b',amount=1.1) # 同上,每一次自增1.1可以加上小数 25 # print(conn.hget('dic0','b')) 26 conn.hmset('h1', {'a': 'a1', 'b': 'b1', 'c': 'c1'}) # 这里的hmset是设置多个值 27 28 # det1,det2=conn.hscan('h1',cursor=0,match=None,count=None) # 这里是把所有的值都取出来, 29 # print(det1,det2) # 0 {b'a': b'a1', b'b': b'b1', b'c': b'c1'}det1是索引值 30 31 data = conn.hscan_iter('h1', match=None, count=12) # 这里是把我们的数据利用yield封装成hscan创建生成器, 32 # 利用生成器的惰性运算,一个一个把数据取出来, 33 34 for k, v in data: 35 print(k, v) 36 """ 37 惰性运算,利用for循环一次取一个值,避免我们数据量过大从而导致内存崩溃 38 b'a' b'a1' 39 b'b' b'b1' 40 b'c' b'c1' 41 """
链接池:
import redis pool = redis.ConnectionPool(host='10.211.55.4', port=6379) r = redis.Redis(connection_pool=pool) r.set('foo', 'Bar') print r.get('foo')
我们先把redis安装上,
然后用pip3 install redis 这里是安装我们的python操作这个redis的模块
打开cmd , 输入D: 回车,目录切换到D盘,
我们的redis的安装包在d盘下面,我们要打开redis文件
在cmd接着输入命令:
D:\Program Files\Redis (redis的文件路径:) redis-server.exe "redis.windows.conf"
如图显示就可以了
我们如果要连接其他的终端,需要跟ip地址绑定,前提是我们要在redis配置项里面做一些改动
在redis的安装包里面把"redis.windows-service.conf"这个文件打开,一般用notepad++即可打开,全局搜索找到bind 把地址改成0.0.0.0
这样就可以连接所有的ip了,否则默认是连接自己的ip
我们的redis就是一个数据库,
它不是存入到硬盘中的数据库,而是暂存到我们的内存中的,这样存取数据会很快,但是不会永久保存,
我们一般会把常用的数据都放到这个redis里面,提高我们的工作效率,
然后它有自己的api,很多操作指令,我后续会把它们整理出来贴上
一个简单的小示例,
import redis # conn=redis.Redis(host='192.168.12.79',port=6379) # 这里是连接我们的电脑的ip地址(在cmd里面输入指令ipconfig在ipv4里面可以看到) conn=redis.Redis(host='127.0.0.1',port=6379) # 这里是连接我们的本地程序 # conn.set('qqx','wahaha') # 我们在redis里面存入一个值,第一次存入,就写到内存中,即便后面注释掉它,依然会执行下面的print操作 val=conn.get('qqx') print(val)
设置过期时间,给指定的key。如下是在redis命令行里面:expire
127.0.0.1:6379> set lmj-name dream # 先设置key value值 OK 127.0.0.1:6379> expire lmj-name 10 # 再设置过期时间,expire 【key】【seconds】 (integer) 1 # 如果设置成功是返回1,如果不成功或者是该key不存在,则返回0 127.0.0.1:6379> get lmj-name "dream"
127.0.0.1:6379> expire lmj 2 # redis没有lmj这个key,设置过期时间不成功,返回0
(integer) 0
在项目中redis的应用,以及该如何跟mysql数据库做同步,相关解决办法,收藏转载博客地址:
https://www.cnblogs.com/xiaozengzeng/p/10872290.html
redis中的发布和订阅
发布者
import redis con=redis.Redis(host='127.0.0.1',port=6379) con.publish('101.8MH','hello form outside')
订阅者
import redis obj=redis.Redis(host='127.0.0.1',port=6379) con=obj.pubsub() con.subscribe('101.8MH') while True: msg=con.parse_response() print(msg)
先运行我们的订阅者让订阅者夯住等待发布者消息推送,然后再运行发布者.
这里是我们的redis的高阶用法:
今日内容: 1. redis 2. 异步非阻塞 3. 代码部署 内容详细: 1. redis 你了解的redis? 你用redis做过什么? - 配合django做缓存,常用且不易修改的数据放进来(博客) - 购物车信息 - Session - 缓存配置文件 - session配置文件中指定使用缓存 - rest api中访问频率控制 - 基于flask、websocket实现的投票系统(redis做消息队列) - scrapy中 - 去重规则 - 调度器:先进先出、后进先出、优先级队列 - pipelines - 起始URL - 商品热点信息 - 计数器 - 排行 为什么redis要做主从复制? 目的是对redis做高可用,为每一个redis实例创建一个备份称为slave,让主和备之间进行数据同步,save/bsave。 主:写 从:读 优点: - 性能提高,从分担读的压力。 - 高可用,一旦主redis挂了,从可以直接代替。 存在问题:当主挂了之后,需要人为手工将从变成主。 redis的sentinel是什么? 帮助我们自动在主从之间进行切换 检测主从中 主是否挂掉,且超过一半的sentinel检测到挂了之后才进行进行切换。 如果主修复好了,再次启动时候,会变成从。 redis的cluster是什么? 集群方案: - redis cluster 官方提供的集群方案。 - codis,豌豆荚技术团队。 - tweproxy,Twiter技术团队。 redis cluster的原理? - 基于分片来完成。 - redis将所有能放置数据的地方创建了 16384 个哈希槽。 - 如果设置集群的话,就可以为每个实例分配哈希槽: - 192.168.1.20【0-5000】 - 192.168.1.21【5001-10000】 - 192.168.1.22【10001-16384】 - 以后想要在redis中写值时, set k1 123 将k1通过crc16的算法,将k1转换成一个数字。然后再将该数字和16384求余,如果得到的余数 3000,那么就将该值写入到 192.168.1.20 实例中。 redis是否可以做持久化? RDB:每隔一段时间对redis进行一次持久化。 - 缺点:数据不完整 - 优点:速度快 AOF:把所有命令保存起来,如果想到重新生成到redis,那么就要把命令重新执行一次。 - 缺点:速度慢,文件比较大 - 优点:数据完整 redis的过期策略。 voltile-lru: 从已设置过期时间的数据集(server.db[i].expires)中挑选最近频率最少数据淘汰 volatile-ttl: 从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰 volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰 allkeys-lru: 从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰 allkeys-random: 从数据集(server.db[i].dict)中任意选择数据淘汰 no-enviction(驱逐):禁止驱逐数据 redis的分布式锁实现。 - 写值并设置超时时间 - 超过一半的redis实例设置成功,就表示加锁完成。 - 使用:安装redlock-py from redlock import Redlock dlm = Redlock( [ {"host": "localhost", "port": 6379, "db": 0}, {"host": "localhost", "port": 6379, "db": 0}, {"host": "localhost", "port": 6379, "db": 0}, ] ) # 加锁,acquire my_lock = dlm.lock("my_resource_name",10000) if my_lock: # J进行操作 # 解锁,release dlm.unlock(my_lock) else: print('获取锁失败') http://www.redis.cn/ 2. 异步非阻塞框架:Tornado 目标:通过一个线程处理N个并发请求。 - 处理请求IO :牛逼起来 - 处理非请求IO:傻逼起来 使用支持tornado异步非阻塞的模块: MySQL Redis SQLALchemy Tornado异步非阻塞本质: 视图函数yield一个futrue对象,futrue对象默认: self._done = False ,请求未完成 self._result = None ,请求完成后返回值,用于传递给回调函数使用。 tornado就会一直去检测futrue对象的_done是否已经变成True。 如果IO请求执行完毕,自动会调用future的set_result方法: self._result = result self._done = True 参考:http://www.cnblogs.com/wupeiqi/p/6536518.html 单台redis的服务器的qbs,读是8万,写是3万,为了提高并发,用户量大的时候可以更快处理用户请求,数据更安全,有更多备份,所以就需要分布式集群,
本质上就是把一部分数据从一台机器上改到多台机器上. redlock redis内部是单进程单线程 redlock安装 使用源码安装,因为在pip库里面还没有它,安装地址:https://github.com/SPSCommerce/redlock-py 这里是下载地址,下载后解压,cmd里面cd到该文件下,
然后执行两条命令,python setup.py build python setup.py install 最后显示redlock-py==1.0.8 就是安装成功 为什么要用这个锁,为了防止两个客户端同时对同一份数据进行操作造成数据丢失. 在redis中我们支持集群,就是可以同时让多个客户端对redis进行操作.这个锁就营运而生了,它是怎么加上的呢,在我们的redis里面加上一个随机字符串,
然后给我们的客户端也加上一个随机字符串,这个时候其他的客户端看到这个字符串就知道是加锁了,就不会对该数据进行操作,会等到锁被释放掉再去执行操作.
在加锁的过程中,我们的这个主从库宕机了,挂掉了,那么这个锁在主从库宕机前就已经加上了,就需要有超时时间,把时间设置上之后,我们的其他客户端就不必遥遥无期的等下去.
还有一种情况就是我们的超时间的设置,如果我们在加锁的过程中,这个过程已经耗时了假设1s,而我们的锁所设置的超时间是0.5s,那么我们把锁设置好了,
就已经过了该锁的超时时间了,此时的锁是没有意义的,不会生效.还有一点是我们的主库如果宕机了,那么哨兵检测到主库挂掉,会把从库提出来作为主库,如果宕机后的主库恢复了,
因为此时已经有主库了,这个恢复后的主库就自动变成从库. 上面是加锁,然后就是释放锁,使用脚本来释放掉锁,当我们在加锁的时候所设定的字符串存在,然后这个字符串的值还必须要跟我们的客户端的值一样,才能删除成功,
通过lua脚本来实现.这样释放掉锁可以避免删除别的客户端获取成功的锁, 还有就是直接向所有的redis实例发送释放锁命令,不关心之前有没有从redis实例中成功获取到锁. 锁的安全和活性失效保障 安全属性:独享(互相排斥),在任意一个时刻,只有一个客户端持有锁. 活性A:无死锁,即便持有锁的客户端崩溃或者网络被分裂,锁仍然可以被获取. 活性B:容错,只要大部分redis节点都活着,客户端留可以获取和释放锁