redis 学习记录

来源:互联网 发布:格式化后如何恢复数据 编辑:程序博客网 时间:2024/06/04 18:31
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。[1] 
Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。
redis的官网地址,非常好记,是redis.io。(特意查了一下,域名后缀io属于国家域名,是british Indian Ocean territory,即英属印度洋领地)

目前,Vmware在资助着redis项目的开发和维护。

doc http://doc.redisfans.com/index.html

5种基本type:String hash list set zsetstringsstring是最简单类型,是二进制安全的 包含任何数据比如图片和对象序列化set name helloget keysetnx 如果k存在返加0 nx note exist 不覆盖,不存在设置新值setnx name hellosetex 设置k的值为string类型的value 并且指定有效期setex namex 10 jak 10秒有效期setrange 设置 指定key的value值 的子字符串get namexiaomingxxxxxx@126.comsetrange name 8 aaaaaa 从下标开始 替换指定长度跟替换的一样get namemset 一次设置多个key的值 失败全不成功mset k1 xiaoming k2 xiaohongmsetnx note exis 不会覆盖已经存在的keygetset 设置key的值 并返回key的旧值getset k1 hellogetrange 获取key的value的子字符串getrange k1 0 3 从0到第3个返回mget 批量获取mget k1 k2incr 递增set k3 10incr k3incrby k4 10 加指定值 key不存在 则设置key 为认为原来的value为0incrby k4 -10decr 对key的值做减减decrby 指定减append 给指定key的字符串追加valueappend k1 world  返回长度strlen 返回值长度strlen k1

hashset类型 是一个string类型的field和value的映射表,它的添加、删除操作都是0(1)(平均)hash特别适合用于存储对象,相较于将对象的每个字段存成单个string 类型将一个对象存在hash中会暂用很少的内在,并且可以方便的存取整个对象hset 设置hash field为指定值  如果key不存在 则先创建hset myhash field hellohset user:001 name jakhget user:001 namehsetnx user:002 name hellohmset 批量设值hmset myhash field hello field2 worldhmget 获取所有健hmget user:002 name age x 批量返回hincrby user:002 age 10 自增hexists hash表字段是否存在hexists user:002 agehlen返回指定hash的key数hlen user:002hdel 删除指定hash的field字段hdel myhash agehkeys 返回hash所有字段hkeys user:002hvals 返回hash所有valuehvals user:002hgetall 获取某个hash中全部的字段和值hgetall user:002


==================list start===========================list是一个链表结构,主要功能是push,pop,获取一个范围的所有值等等,操作中key理解为链表的名字。redis的list类型其实就是一个每个子元素都是string类型的双向链表。我们可以通过push pop操作从链表的头部或者尾部添加删除元素这样list即可以作为栈,又可以作为队列。push 压入一个元素pop  弹出一个元素lpush 从头部压入一个元素 先进后出lpush mylist worldlpush mylist hellolrange mylist 0 -1 取元素hello worldrpush从尾部压入元素  先进先出 队列rpush list2 jakrpush list2  tomlrange list2 0 -1jaktomlinsert 在key对应list的特定位置前或后添加字符串linsert list2 before jak sumlset 设置list中指定下标元素替换掉lset list2 1 updatevlrem 从key对应list中删除N个和value相同的元素(n<0从尾删除,N=0全部删除)lrem list2 2 jak 删除 几个元素ltrim 保留指定key的值范围内的数据ltrim list2 1 -1 把第0个删掉lpop 从list的头部删除元素 并返回删除元素lpop list2 rpop 从尾部弹出一个元素rpop list2lpoplpush 从第一个list的尾部移除元素并添加到第二个list的头部lpoplpush list2 list3lindex 返回名称为key的list中index位置的元素 linex  list2 0lindex list2 1llen 返回key对应list的长度sllen list2==================list end===========================

===========sets 无序集合================sadd myset1 onesadd myset1 twosadd myset1 two  不能增加重复值smembers myset1 查看元素srem 删除srem myset1 onespop 随机弹出元素sdiff 返回所有给定key与第一个Key的差集sdiff myset1 myset2sdiffstore 存储差集的值sdiffstore myset3 myset1 myset2sinter 交集sinter myset1 myset2sinterstore  存储交集的值sunion 返回所有给定key的并集sunion myset1 myset2sunionstore 存储并集smove 从第一key对应的set中移除元素并添加到第二个对诮的set中smove myset1 myset2 three 把three从1移到2中scard 返回名称key的集合个数sismember 测试元素是否是名称为key的Set的元素sismember myset1 two 返回1代表是sismember myset1 twox 返回0代表不是srandmember 随机返回集合的一个元素 ,但不删除元素srandmember myset1====================



=================sorted sets 有序集合=======================是set的一个升级版本 加一个顺序属性zset会自动重新排序, 可以理解为有两列的mysql表一列存value 一列为顺序,操作过程中 key可以理解为名称zadd 向名称为key的zset中添加元素member,score用于排序如果该元素存在,则更新其顺序zadd myzset 1 onezadd myzset 2 twozadd myzset 3 two 会把顺序更新为3zrange myzset 0 -1 withscores 0第一个位置 -1 最后一个zrem 删除名称为key的zset中的元素memberzrem myzset1 onezincrby 以指定值增加如果在名称为key的zset中已经存在元素memebre,则该元素的score增加incremernt否则向该集合中添加该元素,其score的值为incrementzincrby myzset 4 two 对顺序号进行增加-数为减zrank 返回名称为key的zset中memebr元素的排名(按score从小到大排序) 即下标zrank myzset1 twozrevrank 返回名称为key的zset中memebr元素的排名(按score从大到小排序) 即下标zrevrank myzset threezrevrange index降序排序zrevrange myzset 0 -1 withscoreszrangebyscore 返回2到3区间的元素zrangebyscore myzset 2 3 withscoreszcount 返回集合中score在给定区间的数量zcount myzset 2 10zcard 返回集合中所有个数zcard myzsetzremrangebyrank 删除集合中排名在给定区间的元素zremrangebyrank  myzset 2 3<pre code_snippet_id="657920" snippet_file_name="blog_20150503_5_8689354" name="code" class="html">排名
zremrangebyscore 删除集合中给定区间的元素 zremrangebyscore myzset 1 2 删除指定的1-2的元素
<pre code_snippet_id="657920" snippet_file_name="blog_20150503_5_8689354" name="code" class="html">(代表索引 删除从2-3区间的元素)
==================end==========================================

常用命令redis提供了丰富的命令对数据库和各种数据库类型进行操作.这些命令可以在linux终端使用1 健值相关命令2 服务器相关命令keys 返回给定pattern 的所有keykeys * 返回所有健keys my*exists 确认一个key是否存在exists myset 返回0不存在 1存在del 删除一个keyexpire 设置一个key的过期时间expire name 10ttl name 查看还有多少时间过期 (3.0)-2为过期move 将当前数据库中的key转移到其它数据库中select 0  进入0数据库se age 20get agemove age 1 将age 移到1数据库get ageselect 1 进入1数据库get agepersist 移除给定key的过期时间如果expire age 200ttl agepersiste age 对age健 取消过期时间randomkey 随机返回key空间的一个keyrandomkeyrename 重命名rename set2 set200type 返回key的类型type myzset===========健值 相关命令 end====================服务器相关命令ping 测试连接是否存活ping PONG 正常echo 在命令行打印一些内容echo helloworld 输出什么显示什么select 选择数据库 redis 数据库编号0-15我们可以任意选择一个数据库进行存取quit退出客户端连接dbsize 返回当前数据中key的数目info 获取服务器的信息和统计config get 实时传储收到的请求config get dirconfig get * 返回所有可选项flushdb 删除当前选择数据库中的所有keyfuushall 删除所有数据库中的key==========end================

=========高级应用==================安全性主从复制事务处理持久化机制发布订阅消息虚拟内存的使用 安全性============设置客户端连接后进行任何其他指定前需要使用的密码vi /usr/local/redis/etc/redis.conf#requirepass foobaredrequirepass mypassauth 授权(密码)登陆时 redis-cli -a 密码主从复制=============slave server 拥有master的数据Master可以拥有多个slave不会阻塞master 在同步数据时master继续处理client提高系统的伸缩性redis.config改slaveof 192.168.72.130 6379 #指定master的ip和端口masterauth password #这是主机的密码info查看主从 role==============事务处理=====================client在一个连接中发出multi命令时,这个连接会进入一个事务上下文,该连接后续的命令不会立即执行,而是先放到一个队列中,当执行exec命令时,redis会顺序的执行队列中的所有命令getagemulti  把所有命令放入队列setage 10setage 20exec 执行队列中所有命令discard 清空事务队列 回滚乐观锁复杂事务控制session1get agewatch age 监控值(可以对key加乐观锁) 从调用后发生过变化 则整个事务失败,exec discard,unwatch会清空multisession2set age 1000get age session1 set ageexec 失败get age ======持久化机制=====需要经常将内存中的数据同步到硬盘来保持持久化1:snapshotting(快照)默认 将数据存入二进制文件 dump.rdb 可以配置 save 900 1 # 900秒内超过1个key被修改,则发起快照保存save 300 10 # 300秒内超过10个key被修改,则发起快照保存2:append-only file(aof)方式 将我们的写 改存入文件由于快照是在一个时间内发起快照,所以redis意外down掉的话,就会丢失最后一次的修改的数据aof比快照方式更好的持久化性,是由于在aof时,redis会将每一个收到的写命令都 会通过writer函数追加到文件中,当reids重启时会通过重新执行文件中保存的写命令来在内在中重建整个数据库的内容可以通过配置文件告诉redis我们想要通过fsync函数强制os写入磁盘的时机appendonly yes //启用aof持久化方式appendfsync always //收到写命令就立即写入磁盘,最慢,但是保证完全的持久化appendfsync everysec //每秒钟写入磁盘一次,在性能和持久化方面做了很好的折中appendfsync no //完全依赖os,性能最好,持久化没保证======================发布级订阅消息发布订阅(pub/sub)是一种消息通信模式。主要的目的是解除消息发布者和订阅者之间的耦合,redis作为一个pub/sub的serve.在订阅者和发布者之间起到了消息路由的功能订阅者可通过subscribe和psubscribe命令向redis server订阅自已感兴趣的消息类型,redis将信息类型称为通道channel。当发布者通过publish命令向redis server  v发送特定类型的信息时,订阅该信息类型的全部client都会收到此消息客户端1: subscribe tv1 tv2 订阅此频道服务端: psubscribe tv1  helloworld 向tv1发布消息=========================虚拟内存的使用把经常不使用的数据交换到磁盘上vm-enabled yes #开启vm 功能vm-swap-file /tmp redis.swap #交换出来的value保存的文件路径vm-max-memory 1000000 #redis使用的最大内在上限vm-page-size 32  #每个页面的大小32 字节vm-pages 134217728 #最多使用多少页面vm-max-threads 4 #用于执行value对象换入的工作线程数量


使用Redis开发应用程序是一个很愉快的过程,但是就像其他技术一样,基于Redis的应用程序设计你同样需要牢记几点。在之前,你可能已经对关系型数据库开发的那一整个套路了然如胸,而基于Redis的应用程序开发也有许多相似的地方,但是你必须牢记以下两点——Redis是个内存数据库,同时它是单线程的。因此,在使用Redis时,你需要注意以下几点:

1. 掌控储存在Redis中的所有键

数据库的主要功能是储存数据,但是对于开发者来说,因为应用程序需求或者数据使用方法的改变,忽略存储在数据库中的某些数据是非常正常的,在Redis中同样如此。你可能忽视期满某些键,也可能因为应用程序的某个模块弃用而忘掉这些数据。

无论哪种情况,Redis都存储了一些不再使用的数据,平白无故的占用了一些空间。Redis的弱结构数据模式让集中储存的内容很难被弄清,除非你为键使用一套非常成熟的命名法则。使用合适的命名方法会简化你的数据库管理,当你通过你的应用程序或者服务做键的命名空间时(通常情况下是使用冒号来划分键名),你就可以在数据迁移、转换或者删除时轻松的识别。

Redis另一个常见用例是作为热数据项作的第二数据存储,大部分的数据被保存在其他的数据库中,比如PostgreSQL或MongoDB。在这些用例中,当数据从主存储移除时,开发者经常会忘记删除Redis中对应的数据。这种存在跨数据存储的情况下,通常需要做级联删除,这种情况下,可以通过在Redis配置保存特定数据项的所有识别符来实现,从而保证数据在主数据库被删除后,系统会调用一个清理程序来删除所有相关副本和信息。

2. 控制所有键名的长度

在上文我们说过要使用合适的命名规则,并且添加前缀来识别数据走向,因此这一条看起来似乎与之违背。但是,请别忘记,Redis是个内存数据库,键越短你需要的空间就越少。理所当然,当数据库中拥有数百万或者数十亿键时,键名的长度将影响重大。

举个例子:在一个32位的Redis服务器上,如果储存一百万个键,每个值的长度是32-character,那么在使用6-character长度键名时,将会消耗大约96MB的空间,但是如果使用12-character长度的键名时,空间消耗则会提升至111MB左右。随着键的增多,15%的额外开销将产生重大的影响。

3. 使用合适的数据结构

不管是内存使用或者是性能,有的时候数据结构将产生很大的影响,下面是一些可以参考的最佳实践:

取代将数据存储为数千(或者数百万)独立的字符串,可以考虑使用哈希数据结构将相关数据进行分组。哈希表是非常有效率的,并且可以减少你的内存使用;同时,哈希还更有益于细节抽象和代码可读。

合适时候,使用list代替set。如果你不需要使用set特性,List在使用更少内存的情况下可以提供比set更快的速度。

Sorted sets是最昂贵的数据结构,不管是内存消耗还是基本操作的复杂性。如果你只是需要一个查询记录的途径,并不在意排序这样的属性,那么轻建议使用哈希表。

Redis中一个经常被忽视的功能就是bitmaps或者bitsets(V2.2之后)。Bitsets允许你在Redis值上执行多个bit-level操作,比如一些轻量级的分析。

4. 使用SCAN时别使用键

从Redis v2.8开始,SCAN命令已经可用,它允许使用游标从keyspace中检索键。对比KEYS命令,虽然SCAN无法一次性返回所有匹配结果,但是却规避了阻塞系统这个高风险,从而也让一些操作可以放在主节点上执行。

需要注意的是,SCAN 命令是一个基于游标的迭代器。SCAN 命令每次被调用之后, 都会向用户返回一个新的游标,用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。同时,使用SCAN,用户还可以使用keyname模式和count选项对命令进行调整。

SCAN相关命令还包括SSCAN 命令、HSCAN 命令和 ZSCAN 命令,分别用于集合、哈希键及有续集等。

5. 使用服务器端Lua脚本

在Redis使用过程中,Lua脚本的支持无疑给开发者提供一个非常友好的开发环境,从而大幅度解放用户的创造力。如果使用得当,Lua脚本可以给性能和资源消耗带来非常大的改善。取代将数据传送给CPU,脚本允许你在最接近数据的地方执行逻辑,从而减少网络延时和数据的冗余传输。

在Redis中,Lua一个非常经典的用例就是数据过滤或者将数据聚合到应用程序。通过将处理工作流封装到一个脚本中,你只需要调用它就可以在更短的时间内使用很少的资源来获取一个更小的答案。

专家提示:Lua确实非常棒,但是同样也存在一些问题,比如很难进行错误报告和处理。一个明智的方法就是使用Redis的Pub/Sub功能,并且让脚本通过专用信道来推送日志消息。然后建立一个订阅者进程,并进行相应的处理。


1 0
原创粉丝点击