admin 管理员组文章数量: 887021
2024年1月18日发(作者:polarity是什么意思)
redis基本原理、优化和应用示例目录1redis基本原理.........................................................................................................................11.1Redis是什么.................................................................................................................11.2Redis数据类型.............................................................................................................11.3Redis .11.4Redis内存分配原理.....................................................................................................21.21.3231.5Nosql对比...........................................................................................................................4redis优化.................................................................................................................................42.1redis内存优化.............................................................................................................42.2redis性能优化.............................................................................................................52.3压力测试......................................................................................................................62.4Redis监控.....................................................................................................................72.5优化实例......................................................................................................................82.5.1内存优化..........................................................................................................82.5.2性能优化..........................................................................................................8redis应用示例.........................................................................................................................9
1redis基本原理1.1Redis是什么REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。Redis提供了一些丰富的数据结构,包括 lists, sets, ordered sets
以及 hashes ,当然还有和Memcached一样的 strings结构.Redis当然还包括了对这些数据结构的丰富操作。1.2Redis数据类型Redis最为常用的数据类型主要有以下五种:StringHashListSetSorted set1.3Redis VS memcached1)性能Redis在存储小数据时比Memcached性能更高;而在100k以上的数据中,Memcached性能要高于Redis;不过无论你使用哪一个,每秒处理请求的次数都不会成为瓶颈。内存使用率基本key-value,memcached的内存使用率比redis高;而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。3)4)数据持久化和同步如果有持久化或同步的需求,则选择redisRedis支持更多的数据结构和丰富的数据操作/commands/2)
1.4Redis内存分配原理1.4.1String一个set hello world命令最终(中间会malloc,free的我们不考虑)会产生4个对象,一个dictEntry(12字节),一个sds用于存储key,还有一个redisObject(12字节),还有一个存储string的对象除了包含字符串本生之外,还有一个sds
header和额外的一个字节作为字符串结尾共9个字节.这个命令最终申请的内存为16(dictEtnry) + 16 (redisObject) + 16(“hello”) +
16(“world”),一共64字节.注意如果key或者value的字符串长度+9字节超过16字节,则实际申请的内存大小32字节.String类型内存计算公式:string类型的内存大小 = 键值个数 * (dictEntry大小 + redisObject大小 + 包含key的sds大小 + 包含value的sds大小) + bucket个数 * 4测试脚本#! /bin/bashredis-cli info|grep used_memory:for (( start = 10000; start < 30000; start++ ))do
redis-cli set a$start baaaaaaaa$start > /dev/nulldoneredis-cli info|grep used_memory:预估值>>> 20000 * (16 + 16 + 16 + 32) + 32768 * 417310721.4.2Zipmap对于一个普通的subkey和value,只需要额外的3个字节(keylen,valuelen,freelen)来存储,另外的hash key也只需要额外的2个字节(zm头尾)来存储subkey的个数和结束符.zipmap类型的内存大小 = hashkey个数 * (dictEntry大小 + redisObject大小 + 包含key的sds大小 + subkey的总大小) + bucket个数 * 4测试脚本#! /bin/bashredis-cli info|grep used_memory:for (( start = 100; start < 200; start++ ))do for (( start2 = 100; start2 < 400; start2++ )) do redis-cli hset test$start a$start2 "1" > /dev/null done
doneredis-cli info|grep used_memory:这里subkey是同时申请的的,大小是300 * (5 + 3) + 2 =2402字节,实际申请的内存为2560.另外100hashkey的bucket是128.所以总的预估大小为>>> 100 * (16 + 16 + 16 + 2560) + 128 * 42613121.5Nosql对比类型部分代表特点顾名思义,是按列存储数据的。Hbase列存储CassandraHypertable最大的特点是方便存储结构化和半结构化数据,方便做数据压缩,对针对某一列或者某几列的查询有非常大的IO优势。文档存储一般用类似json的格MongoDB文档存储CouchDB式存储,存储的内容是文档型的。这样也就有有机会对某些字段建立索引,实现关系数据库的某些功能。Tokyo Cabinet / Tyrantkey-value存储Berkeley DBMemcacheDBRedisNeo4J图存储FlockDBInfoGriddb4o对象存储VersantBerkeley DB XMLBaseX可以通过key快速查询到其value。一般来说,存储不管value的格式,照单全收。(Redis包含了其他功能)图形关系的最佳存储。使用传统关系数据库来解决的话性能低下,而且设计使用不方便。通过类似面向对象语言的语法操作数据库,通过对象的方式存取数据。xml数据库高效的存储XML数据,并支持XML的内部查询语法,比如
XQuery,Xpath。2redis优化2.1redis内存优化1)2)不要开启Redis的VM选项,即虚拟内存功能。其内存管理成本也非常的高。最好设置下中的maxmemory选项,该选项是告诉Redis当使用了多少物理内存后就开始拒绝后续的写入请求,该参数能很好的保护好你的Redis不会因为使用了过多的物理内存而导致swap。压缩key-value数值替换字符串,对字符串采用kryo或protobuf压缩。内存分配器3)4)Redis在编译时,会先判断是否使用tcmalloc,如果是,会用tcmalloc对应的函数替换掉标准的libc中的函数实现。其次会判断jemalloc是否使得,最后如果都没有使用才会用标准的libc中的内存管理函数。在数据大于1k的情况下,三者对应的内存使用率差异不大;在数据小于1k的情况下,内存使用率tcmalloc > jemalloc > libc5)Redis为不同数据类型分别提供了一组参数来控制内存使用, Redis Hash是value内部为一个HashMap,如果该Map的成员数比较少,则会采用类似一维线性的紧凑格式来存储该Map, 即省去了大量指针的内存开销,这个参数控制对应在配置文件中下面2项:hash-max-zipmap-entries 64
hash-max-zipmap-value 512
含义是当value这个Map内部不超过多少个成员时会采用线性紧凑格式存储,默认是64,即value内部有64个以下的成员就是使用线性紧凑存储,超过该值自动转成真正的HashMap。hash-max-zipmap-value 含义是当 value这个Map内部的每个成员值长度不超过多少字节就会采用线性紧凑存储来节省空间。以上2个条件任意一个条件超过设置值都会转换成真正的HashMap,也就不会再节省内存了。
2.2redis性能优化1)网络与通信延迟连接池管道异步批量执行2)redis单线程属性使用更多的redis实例Redis为单进程单线程模式,采用队列模式将并发访问变为串行访问。Redis本身没有锁的概念,Redis对于多个客户端连接并不存在竞争3)低效操作产生的延迟读写分离,慢操作分离slowlog4)延迟由fork产生5)延迟由swapping(操作系统分页)产生/proc/pid/smaps6)AOF 和硬盘I/O操作延迟appendfsync everysec每秒都会执行fsync。fsync 由一个单独线程执行7)数据过期造成的延迟lazy 方式,在key被请求的时候才检查是否过期。 to be already 方式,每0.1秒进行一次过期检查。active过期模式是自适应的,每过100毫秒开始一次过期检查(每秒10次)如果发现有超过指定数量25%的key已经过期就会循环执行大量key同时过期会对系统延迟造成影响2.3压力测试Usage: redis-benchmark [-h
-h
-k
量。它可以提供的数据有:某一类 key 值的访问频率如何,有多少值设置了过期时间,某一类 key 值使用内存的大小,这很方便让我们能排查哪些
key 不常用或者压根不用。Found 10000 keys containing strings, like:
user_profile_3897016, user_profile_3339430,
user_profile_3240266, user_profile_2883394,
user_profile_3969781, user_profile_3256693,
user_profile_3766796, user_profile_2051997,
user_profile_2817842, user_profile_1453480Found 16000 keys containing zsets, like:
notification_3109439, notification_3634040,
notification_2318378, notification_3871169,
notification_3980323, notification_3427141,
notification_1639845, notification_2823390,
notification_2658377, notification_4153039Key | Memory
Usage | Expiry Proportion | Last Access Time
---------------------------------------------------+--------------+-------------------+---------------------------------------------------
notification_3109439 | 88.14%
| 0.0% | 2 minutes
user_profile_3897016 | 11.86%
| 99.98% | 20 seconds
---------------------------------------------------+--------------+-------------------+---------------------------------------------2.5优化实例2.5.1内存优化1)通过序列化方式优化Json-case:{"uid":"02:00:00:00:00:00","clickData":{"20131019":{"dailyInfo":{"1":200,"2":600,"3":300}}},"impData":{"20131013":{"dailyInfo":{"1":200,"2":600,"3":300}}},"firstClickTime":{"1003":"2012-10-20 11:20:20","1002":"2012-10-20
11:20:20","1005":"2012-10-20 11:20:20","1004":"2012-10-20
11:20:20","1007":"2012-10-20 11:20:20","1006":"2012-10-20
11:20:20","1008":"2012-10-20 11:20:20","1009":"2012-10-20
11:20:20","1010":"2012-10-20 11:20:20","1011":"2012-10-20
11:20:20","1012":"2012-10-20 11:20:20"}}改为kyro或protobuf序列化可以节约50%内存2)基于hash-ziplist特性优化Hmset-case: (key,value=[{item1},...,{item600}])缺省配置:hash-max-ziplist-entries 512hash-max-ziplist-value 64优化配置:hash-max-ziplist-entries 640hash-max-ziplist-value 642.5.2性能优化Case:19个读消费端+3个写消费端3redis应用示例1、水平拆分我们采用的"一致性HASH算法"(Consistent Hashing)是KetamaHash 算法。介绍如下: Ketama is an implementation of a consistent hashing algorithm, meaning you can add or remove servers from the memcached pool without causing a complete remap of all keys.
Here’s how it works:
* Take your list of servers (eg: 1.2.3.4:11211, 5.6.7.8:11211, 9.8.7.6:11211)
* Hash each server string to several (100-200) unsigned ints
* Conceptually, these numbers are placed on a circle called the continuum. (imagine a clock face that goes from 0 to 2^32)
* Each number links to the server it was hashed from, so servers appear
at several points on the continuum, by each of the numbers they hashed to.
* To map a key->server, hash your key to a single unsigned int, and find the next biggest number on the continuum. The server linked to that number is the correct server for that key.
* If you hash your key to a value near 2^32 and there are no points on the continuum greater than your hash, return the first server in the continuum.
If you then add or remove a server from the list, only a small proportion of keys end up mapping to different servers.2、读写示例Jedis jedis =
tance().getRedisPool().getRedisResource();(key,value);(keys);Pipeline pipe = ned();(key,value);3、redis luaredis嵌入lua脚本语言,减少客户端与服务端的交互。Case:redis-cli SCRIPT LOAD "return 'hello world'"=> "5332031c6b470dc5a0dd9b4bf2030dea6d65de91"redis-cli EVALSHA 5332031c6b470dc5a0dd9b4bf2030dea6d65de91 0
=> "hello world"客户端基于sha调用,也可以直接使用eval
版权声明:本文标题:Redis基本原理、优化和应用示例 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1705517620h488185.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论