• memcached


    Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。

    安装

    sudo apt install libevent-dev
    
    wget http://memcached.org/latest(最新版)
    
    tar -zxvf latest(注意:是latest)
    
    cd memcached-1.x.x
    
    ./configure
    
    make
    make test
    
    sudo make install
    
    至此安装完成
    linux
    memcached -d -m 10    -u root -l 10.211.55.4 -p 12000 -c 256 -P /tmp/memcached.pid
    
    -d是启动一个守护进程;
    -m是分配给Memcache使用的内存数量,单位是MB;
    -u是运行Memcache的用户;
    -l是监听的服务器IP地址,可以有多个地址;
    -p是设置Memcache监听的端口,,最好是1024以上的端口;
    -c是最大运行的并发连接数,默认是1024;
    -P是设置保存Memcache的pid文件。
    
    
    详细参数:注意default
    -p, --port=<num>          TCP port to listen on (default: 11211)
    -U, --udp-port=<num>      UDP port to listen on (default: 0, off)
    -s, --unix-socket=<file>  UNIX socket to listen on (disables network support)
    -A, --enable-shutdown     enable ascii "shutdown" command
    -a, --unix-mask=<mask>    access mask for UNIX socket, in octal (default: 700)
    -l, --listen=<addr>       interface to listen on (default: INADDR_ANY)
    -d, --daemon              run as a daemon
    -r, --enable-coredumps    maximize core file limit
    -u, --user=<user>         assume identity of <username> (only when run as root)
    -m, --memory-limit=<num>  item memory in megabytes (default: 64)
    -M, --disable-evictions   return error on memory exhausted instead of evicting
    -c, --conn-limit=<num>    max simultaneous connections (default: 1024)
    -k, --lock-memory         lock down all paged memory
    -v, --verbose             verbose (print errors/warnings while in event loop)
    -vv                       very verbose (also print client commands/responses)
    -vvv                      extremely verbose (internal state transitions)
    -h, --help                print this help and exit
    -i, --license             print memcached and libevent license
    -V, --version             print version and exit
    -P, --pidfile=<file>      save PID in <file>, only used with -d option
    -f, --slab-growth-factor=<num> chunk size growth factor (default: 1.25)
    -n, --slab-min-size=<bytes> min space used for key+value+flags (default: 48)
    -L, --enable-largepages  try to use large memory pages (if available)
    -D <char>     Use <char> as the delimiter between key prefixes and IDs.
                  This is used for per-prefix stats reporting. The default is
                  ":" (colon). If this option is specified, stats collection
                  is turned on automatically; if not, then it may be turned on
                  by sending the "stats detail on" command to the server.
    -t, --threads=<num>       number of threads to use (default: 4)
    -R, --max-reqs-per-event  maximum number of requests per event, limits the
                              requests processed per connection to prevent 
                              starvation (default: 20)
    -C, --disable-cas         disable use of CAS
    -b, --listen-backlog=<num> set the backlog queue limit (default: 1024)
    -B, --protocol=<name>     protocol - one of ascii, binary, or auto (default: auto-negotiate)
    -I, --max-item-size=<num> adjusts max item size
                              (default: 1m, min: 1k, max: 1024m)
    -F, --disable-flush-all   disable flush_all command
    -X, --disable-dumping     disable stats cachedump and lru_crawler metadump
    -W  --disable-watch       disable watch commands (live logging)
    -Y, --auth-file=<file>    (EXPERIMENTAL) enable ASCII protocol authentication. format:
                              user:pass
    user2:pass2
    
    -e, --memory-file=<file>  (EXPERIMENTAL) mmap a file for item memory.
                              use only in ram disks or persistent memory mounts!
                              enables restartable cache (stop with SIGUSR1)
    -o, --extended            comma separated list of extended options
                              most options have a 'no_' prefix to disable
       - maxconns_fast:       immediately close new connections after limit (default: enabled)
       - hashpower:           an integer multiplier for how large the hash
                              table should be. normally grows at runtime. (default starts at: 0)
                              set based on "STAT hash_power_level"
       - tail_repair_time:    time in seconds for how long to wait before
                              forcefully killing LRU tail item.
                              disabled by default; very dangerous option.
       - hash_algorithm:      the hash table algorithm
                              default is murmur3 hash. options: jenkins, murmur3
       - no_lru_crawler:      disable LRU Crawler background thread.
       - lru_crawler_sleep:   microseconds to sleep between items
                              default is 100.
       - lru_crawler_tocrawl: max items to crawl per slab per run
                              default is 0 (unlimited)
       - resp_obj_mem_limit:  limit in megabytes for connection response objects.
                              do not adjust unless you have high (100k+) conn. limits.
                              0 means unlimited (default: 0)
       - read_buf_mem_limit:  limit in megabytes for connection read buffers.
                              do not adjust unless you have high (100k+) conn. limits.
                              0 means unlimited (default: 0)
       - no_lru_maintainer:   disable new LRU system + background thread.
       - hot_lru_pct:         pct of slab memory to reserve for hot lru.
                              (requires lru_maintainer, default pct: 20)
       - warm_lru_pct:        pct of slab memory to reserve for warm lru.
                              (requires lru_maintainer, default pct: 40)
       - hot_max_factor:      items idle > cold lru age * drop from hot lru. (default: 0.20)
       - warm_max_factor:     items idle > cold lru age * this drop from warm. (default: 2.00)
       - temporary_ttl:       TTL's below get separate LRU, can't be evicted.
                              (requires lru_maintainer, default: 61)
       - idle_timeout:        timeout for idle connections. (default: 0, no timeout)
       - slab_chunk_max:      (EXPERIMENTAL) maximum slab size in kilobytes. use extreme care. (default: 512)
       - watcher_logbuf_size: size in kilobytes of per-watcher write buffer. (default: 256)
       - worker_logbuf_size:  size in kilobytes of per-worker-thread buffer
                              read by background thread, then written to watchers. (default: 64)
       - track_sizes:         enable dynamic reports for 'stats sizes' command.
       - no_hashexpand:       disables hash table expansion (dangerous)
       - modern:              enables options which will be default in future.
                              currently: nothing
       - no_modern:           uses defaults of previous major version (1.4.x)
    
       - External storage (ext_*) related options (see: https://memcached.org/extstore)
       - ext_path:            file to write to for external storage.
                              ie: ext_path=/mnt/d1/extstore:1G
       - ext_page_size:       size in megabytes of storage pages. (default: 64)
       - ext_wbuf_size:       size in megabytes of page write buffers. (default: 4)
       - ext_threads:         number of IO threads to run. (default: 1)
       - ext_item_size:       store items larger than this (bytes, default 512)
       - ext_item_age:        store items idle at least this long (seconds, default: no age limit)
       - ext_low_ttl:         consider TTLs lower than this specially (default: 0)
       - ext_drop_unread:     don't re-write unread values during compaction (default: disabled)
       - ext_recache_rate:    recache an item every N accesses (default: 2000)
       - ext_compact_under:   compact when fewer than this many free pages
                              (default: 1/4th of the assigned storage)
       - ext_drop_under:      drop COLD items when fewer than this many free pages
                              (default: 1/4th of the assigned storage)
       - ext_max_frag:        max page fragmentation to tolerage (default: 0.80)
       - slab_automove_freeratio: ratio of memory to hold free as buffer.
                              (see doc/storage.txt for more info, default: 0.010)
    参数

    连接

    telnet 127.0.0.1 11211
     1 set key flags exptime bytes [noreply] 
     2 value 
     3 
     4 key:键值 key-value 结构中的 key,用于查找缓存值。
     5 flags:可以包括键值对的整型参数,客户机使用它存储关于键值对的额外信息 。
     6 exptime:在缓存中保存键值对的时间长度(以秒为单位,0 表示永远)
     7 bytes:在缓存中存储的字节数
     8 noreply(可选): 该参数告知服务器不需要返回数据
     9 value:存储的值(始终位于第二行)(可直接理解为key-value结构中的value)
    10 
    11 '''
    12 set foo 0 0 9
    13 memcached
    14 STORED
    15 
    16 get runoob
    17 VALUE runoob 0 9
    18 memcached
    19 
    20 END
    21 '''
    22 
    23 
    24 STORED:保存成功后输出。
    25 ERROR:在保存失败后输出。
    set  如果set的key已经存在,该命令可以更新该key所对应的原来的数据,也就是实现更新的作用。
     1 add key flags exptime bytes [noreply]
     2 value
     3 
     4 参数同set
     5 
     6 add new_key 0 0 10
     7 data_value
     8 STORED
     9 get new_key
    10 VALUE new_key 0 10
    11 data_value
    12 END
    13 
    14 
    15 STORED:保存成功后输出。
    16 NOT_STORED :在保存失败后输出。
    add  如果 add 的 key 已经存在,则不会更新数据(过期的 key 会更新),之前的值将仍然保持相同,并且您将获得响应 NOT_STORED
     1 replace key flags exptime bytes [noreply]
     2 value
     3 
     4 参数同set
     5 
     6 '''
     7 add mykey 0 0 10
     8 data_value
     9 STORED
    10 get mykey
    11 VALUE mykey 0 10
    12 data_value
    13 END
    14 replace mykey 0 0 16
    15 some_other_value
    16 get mykey
    17 VALUE mykey 0 16
    18 some_other_value
    19 END
    20 '''
    21 
    22 
    23 STORED:保存成功后输出。
    24 NOT_STORED:执行替换失败后输出。
    replace 如果 key 不存在,则替换失败,并且您将获得响应 NOT_STORED。
     1 append key flags exptime bytes [noreply]
     2 value
     3 
     4 
     5 参数同set
     6 
     7 
     8 set foo 0 0 9
     9 memcached
    10 STORED
    11 get foo
    12 VALUE foo 0 9
    13 memcached
    14 END
    15 append foo 0 0 5
    16 redis
    17 STORED
    18 get foo
    19 VALUE foo 0 14
    20 memcachedredis
    21 END
    22 
    23 
    24 
    25 STORED:保存成功后输出。
    26 NOT_STORED:该键在 Memcached 上不存在。
    27 CLIENT_ERROR:执行错误。
    append 命令用于向已存在 key(键) 的 value(数据值) 后面追加数据 。
     1 prepend key flags exptime bytes [noreply]
     2 value
     3 
     4 参数同set
     5 
     6 
     7 set foo 0 0 9
     8 memcached
     9 STORED
    10 get foo
    11 VALUE foo 0 9
    12 memcached
    13 END
    14 prepend foo 0 0 5
    15 redis
    16 STORED
    17 get foo
    18 VALUE foo 0 14
    19 redismemcached
    20 END
    prepend 命令用于向已存在 key(键) 的 value(数据值) 前面追加数据 。
     1 '''
     2 Memcached CAS(Check-And-Set 或 Compare-And-Swap) 命令用于执行一个"检查并设置"的操作
     3 它仅在当前客户端最后一次取值后,该key 对应的值没有被其他客户端修改的情况下, 才能够将值写入。
     4 检查是通过cas_token参数进行的, 这个参数是Memcach指定给已经存在的元素的一个唯一的64位值。
     5 '''
     6 
     7 cas key flags exptime bytes unique_cas_token [noreply]
     8 value
     9 
    10 
    11 
    12 unique_cas_token通过 gets 命令获取的一个唯一的64位值。
    13 其他参数同set
    14 
    15 
    16 '''
    17 要在 Memcached 上使用 CAS 命令,你需要从 Memcached 服务商通过 gets 命令获取令牌(token)。
    18 gets 命令的功能类似于基本的 get 命令。两个命令之间的差异在于,gets 返回的信息稍微多一些:64 位的整型值非常像名称/值对的 "版本" 标识符。
    19 
    20 如果没有设置唯一令牌,则 CAS 命令执行错误。
    21 如果键 key 不存在,执行失败。
    22 添加键值对。
    23 通过 gets 命令获取唯一令牌。
    24 使用 cas 命令更新数据
    25 使用 get 命令查看数据是否更新
    26 '''
    27 
    28 cas tp 0 0 9
    29 ERROR             <− 缺少 token
    30 
    31 cas tp 0 0 9 2
    32 memcached
    33 NOT_FOUND         <− 键 tp 不存在
    34 
    35 set tp 0 0 9
    36 memcached
    37 STORED
    38 
    39 gets tp
    40 VALUE tp 0 9 1
    41 memcached
    42 END
    43 
    44 cas tp 0 0 5 1
    45 redis
    46 STORED
    47 
    48 get tp
    49 VALUE tp 0 5
    50 redis
    51 END
    52 
    53 
    54 STORED:保存成功后输出。
    55 ERROR:保存出错或语法错误。
    56 EXISTS:在最后一次取值后另外一个用户也在更新该数据。
    57 NOT_FOUND:Memcached 服务上不存在该键值。
    CAS
    1 get key
    2 
    3 get key1 key2 key3
    get 命令获取存储在 key(键) 中的 value(数据值) ,如果 key 不存在,则返回空。
    1 用法同get
    2 输出中最后一列是该key的CAS令牌
    gets 命令获取带有 CAS 令牌存 的 value(数据值) ,如果 key 不存在,则返回空。
     1 delete key [noreply]
     2 
     3 
     4 
     5 
     6 set foo 0 0 9
     7 memcached
     8 STORED
     9 get foo
    10 VALUE foo 0 9
    11 memcached
    12 END
    13 delete foo
    14 DELETED
    15 get foo
    16 END
    17 delete foo
    18 NOT_FOUND
    19 
    20 
    21 DELETED:删除成功。
    22 ERROR:语法错误或删除失败。
    23 NOT_FOUND:key 不存在。
    delete 命令用于删除已存在的 key(键)。
     1 incr 与 decr 命令用于对已存在的 key(键) 的数字值进行自增或自减操作。
     2 incr 与 decr 命令操作的数据必须是十进制的32位无符号整数。
     3 如果 key 不存在返回 NOT_FOUND,如果键的值不为数字,则返回 CLIENT_ERROR,其他错误返回 ERROR。
     4 
     5 
     6 
     7 incr key increment_value
     8 
     9 increment_value: 增加的数值。
    10 
    11 set visitors 0 0 2
    12 10
    13 STORED
    14 get visitors
    15 VALUE visitors 0 2
    16 10
    17 END
    18 incr visitors 5
    19 15
    20 get visitors
    21 VALUE visitors 0 2
    22 15
    23 END
    24 
    25 
    26 
    27 
    28 decr key decrement_value
    29 
    30 decrement_value: 减少的数值。
    31 
    32 
    33 set visitors 0 0 2
    34 10
    35 STORED
    36 get visitors
    37 VALUE visitors 0 2
    38 10
    39 END
    40 decr visitors 5
    41 5
    42 get visitors
    43 VALUE visitors 0 1
    44 5
    45 END
    incr 与 decr
     1 stats
     2 STAT pid 1162
     3 STAT uptime 5022
     4 STAT time 1415208270
     5 STAT version 1.4.14
     6 STAT libevent 2.0.19-stable
     7 STAT pointer_size 64
     8 STAT rusage_user 0.096006
     9 STAT rusage_system 0.152009
    10 STAT curr_connections 5
    11 STAT total_connections 6
    12 STAT connection_structures 6
    13 STAT reserved_fds 20
    14 STAT cmd_get 6
    15 STAT cmd_set 4
    16 STAT cmd_flush 0
    17 STAT cmd_touch 0
    18 STAT get_hits 4
    19 STAT get_misses 2
    20 STAT delete_misses 1
    21 STAT delete_hits 1
    22 STAT incr_misses 2
    23 STAT incr_hits 1
    24 STAT decr_misses 0
    25 STAT decr_hits 1
    26 STAT cas_misses 0
    27 STAT cas_hits 0
    28 STAT cas_badval 0
    29 STAT touch_hits 0
    30 STAT touch_misses 0
    31 STAT auth_cmds 0
    32 STAT auth_errors 0
    33 STAT bytes_read 262
    34 STAT bytes_written 313
    35 STAT limit_maxbytes 67108864
    36 STAT accepting_conns 1
    37 STAT listen_disabled_num 0
    38 STAT threads 4
    39 STAT conn_yields 0
    40 STAT hash_power_level 16
    41 STAT hash_bytes 524288
    42 STAT hash_is_expanding 0
    43 STAT expired_unfetched 1
    44 STAT evicted_unfetched 0
    45 STAT bytes 142
    46 STAT curr_items 2
    47 STAT total_items 6
    48 STAT evictions 0
    49 STAT reclaimed 1
    50 END
    51 
    52 
    53 
    54 pid: memcache服务器进程ID
    55 uptime:服务器已运行秒数
    56 time:服务器当前Unix时间戳
    57 version:memcache版本
    58 pointer_size:操作系统指针大小
    59 rusage_user:进程累计用户时间
    60 rusage_system:进程累计系统时间
    61 curr_connections:当前连接数量
    62 total_connections:Memcached运行以来连接总数
    63 connection_structures:Memcached分配的连接结构数量
    64 cmd_get:get命令请求次数
    65 cmd_set:set命令请求次数
    66 cmd_flush:flush命令请求次数
    67 get_hits:get命令命中次数
    68 get_misses:get命令未命中次数
    69 delete_misses:delete命令未命中次数
    70 delete_hits:delete命令命中次数
    71 incr_misses:incr命令未命中次数
    72 incr_hits:incr命令命中次数
    73 decr_misses:decr命令未命中次数
    74 decr_hits:decr命令命中次数
    75 cas_misses:cas命令未命中次数
    76 cas_hits:cas命令命中次数
    77 cas_badval:使用擦拭次数
    78 auth_cmds:认证命令处理的次数
    79 auth_errors:认证失败数目
    80 bytes_read:读取总字节数
    81 bytes_written:发送总字节数
    82 limit_maxbytes:分配的内存总大小(字节)
    83 accepting_conns:服务器是否达到过最大连接(0/184 listen_disabled_num:失效的监听数
    85 threads:当前线程数
    86 conn_yields:连接操作主动放弃数目
    87 bytes:当前存储占用的字节数
    88 curr_items:当前存储的数据总数
    89 total_items:启动以来存储的数据总数
    90 evictions:LRU释放的对象数目
    91 reclaimed:已过期的数据条目来存储新数据的数目
    stats 命令用于返回统计信息例如 PID(进程号)、版本号、连接数等。
     1 stats items
     2 STAT items:1:number 1
     3 STAT items:1:age 7
     4 STAT items:1:evicted 0
     5 STAT items:1:evicted_nonzero 0
     6 STAT items:1:evicted_time 0
     7 STAT items:1:outofmemory 0
     8 STAT items:1:tailrepairs 0
     9 STAT items:1:reclaimed 0
    10 STAT items:1:expired_unfetched 0
    11 STAT items:1:evicted_unfetched 0
    12 END
    stats items 命令用于显示各个 slab 中 item 的数目和存储时长(最后一次访问距离现在的秒数)。
     1 stats slabs
     2 STAT 1:chunk_size 96
     3 STAT 1:chunks_per_page 10922
     4 STAT 1:total_pages 1
     5 STAT 1:total_chunks 10922
     6 STAT 1:used_chunks 1
     7 STAT 1:free_chunks 10921
     8 STAT 1:free_chunks_end 0
     9 STAT 1:mem_requested 71
    10 STAT 1:get_hits 0
    11 STAT 1:cmd_set 1
    12 STAT 1:delete_hits 0
    13 STAT 1:incr_hits 0
    14 STAT 1:decr_hits 0
    15 STAT 1:cas_hits 0
    16 STAT 1:cas_badval 0
    17 STAT 1:touch_hits 0
    18 STAT active_slabs 1
    19 STAT total_malloced 1048512
    20 END
    stats slabs 命令用于显示各个slab的信息,包括chunk的大小、数目、使用情况等。
    1 stats sizes 命令用于显示所有item的大小和个数。
    2 
    3 该信息返回两列,第一列是 item 的大小,第二列是 item 的个数。
    4 
    5 
    6 stats sizes
    7 STAT 96 1
    8 END
    stats sizes
     1 flush_all 命令用于清理缓存中的所有 key=>value(键=>值) 对。
     2 该命令提供了一个可选参数 time,用于在制定的时间后执行清理缓存操作。
     3 
     4 
     5 flush_all [time] [noreply]
     6 
     7 
     8 set foo 0 900 9
     9 memcached
    10 STORED
    11 get foo
    12 VALUE foo0 9
    13 memcached
    14 END
    15 flush_all
    16 OK
    17 get foo
    18 END
    flush_all

    Python    memcached

    pip3 install python-memcached

    import memcache
     
    mc = memcache.Client(['127.0.0.1:11211'], debug=True)
    mc.set("foo", "bar")
    ret = mc.get('foo')
    print ret
    
    
    # debug = True 表示运行出现错误时,现实错误信息,上线后移除该参数。就跟django的settings中的debug一样
    其原理是在内存维护一个主机列表,且集群中主机的权重值和主机在列表中重复出现的次数成正比,权重值就类似pyqt5中的stretch参数
    集群操作(弹簧)
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 import memcache
     4 
     5 mc = memcache.Client(['127.0.0.1:11211'], debug=True)
     6 # add  添加一条键值对,如果已经存在的 key,重复执行add操作异常
     7 mc.add('k1', 'v1')
     8 # mc.add('k1', 'v2') # 报错
     9 
    10 
    11 
    12 
    13 # replace 修改某个key的值,如果key不存在,则异常
    14 # 如果memcache中存在kkkk,则替换成功,否则异常
    15 mc.replace('kkkk','999')
    16 
    17 
    18 
    19 
    20 # set            设置一个键值对,如果key不存在,则创建,如果key存在,则修改
    21 #set_multi   设置多个键值对,如果key不存在,则创建,如果key存在,则修改
    22 mc.set('key0', 'asdasd')
    23 mc.set_multi({'key1': 'val1', 'key2': 'val2'})
    24 
    25 
    26 
    27 
    28 # delete             在Memcached中删除指定的一个键值对
    29 # delete_multi    在Memcached中删除指定的多个键值对
    30 mc.delete('key0')
    31 mc.delete_multi(['key1', 'key2'])
    32 
    33 
    34 
    35 
    36 # get            获取一个键值对
    37 # get_multi   获取多一个键值对
    38 val = mc.get('key0')
    39 item_dict = mc.get_multi(["key1", "key2", "key3"])
    40 
    41 
    42 
    43 # append    修改指定key的值,在该值 后面 追加内容
    44 # prepend   修改指定key的值,在该值 前面 插入内容
    45 k1='v1'
    46 mc.append('k1', 'after')
    47 # k1 = "v1after"
    48 mc.prepend('k1', 'before')
    49 # k1 = "beforev1after"
    50 
    51 
    52 
    53 
    54 # incr  自增,将Memcached中的某一个值增加 N ( N默认为1 )
    55 # decr 自减,将Memcached中的某一个值减少 N ( N默认为1 )
    56 mc.set('k1', '777')
    57 mc.incr('k1')
    58 # k1 = 778
    59 mc.incr('k1', 10)
    60 # k1 = 788
    61 mc.decr('k1')
    62 # k1 = 787
    63 mc.decr('k1', 10)
    64 # k1 = 777
    65 
    66 
    67 
    68 
    69 '''
    70 gets 和 cas
    71 
    72 '''
    73 mc = memcache.Client(['127.0.0.1:11211'], debug=True, cache_cas=True)
    74  
    75 v = mc.gets('count')
    76 # mc.cas('count', "100")  就报错 
    77 # 如果有人在gets之后和cas之前修改了product_count,那么,下面的设置将会执行失败,剖出异常,从而避免非正常数据的产生
    78 mc.cas('count', "200")
    79 '''
    80 比如两个人去银行往一个户头存钱
    81 原来有100块
    82 如果两人都存了100快
    83 那么两个人的缓存数据都会是200块
    84 但是怎么可以只有200块呢,亏了喂
    85 用set 和get就会这个样只
    86 ''
    上面提到的其他操作,介绍与上面结合
  • 相关阅读:
    m_Orchestrate learning system---三、session使用完整流程是什么
    m_Orchestrate learning system---四、多看参考文档很多事情很轻松就解决了
    m_Orchestrate learning system---五、学的越多,做的越快
    m_Orchestrate learning system---六、善用组件插件的好处是什么
    m_Orchestrate learning system---七、如何快速学好前端
    cocos2d0基础知识三个音符
    URAL 1727. Znaika&#39;s Magic Numbers(数学 vector)
    第13周项目2-纯虚函数形类家庭
    [cocos2dx注意事项009]试用quick-cocos2dx-2.2.4
    百度之星 1004 Labyrinth
  • 原文地址:https://www.cnblogs.com/JcrLive/p/12460030.html
Copyright © 2020-2023  润新知