`
brandNewUser
  • 浏览: 456094 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Redis hash tag进行分槽导致的问题

阅读更多
我们已经对redis cluster中的key进行了一定的分槽,但是导致了redis节点数据的不均匀分布,三个节点数据量大小对比:5:1:1,但更加恐怖的是内存使用对比,在最多的一个进程中占用超过900M,而最少的一个进程仅60M。
 
对比redis的dump文件,是其他两个的20倍
 
-rw-r--r--. 1 root root  14448246 8月  19 18:45 dump.6388.rdb
-rw-r--r--. 1 root root 279497287 8月  19 18:38 dump.6389.rdb
-rw-r--r--. 1 root root  14199864 8月  19 18:35 dump.6390.rdb
 
 

 Redis启动内存配置

 
可以参考知乎上的回答:https://www.zhihu.com/question/31102463
 
通过redis的config get *命令,可以查看redis配置中所有字段,其中可以看到。
 
 13) "maxmemory"
 14) "0"
 15) "maxmemory-samples"
 16) "5"
113) "maxmemory-policy"
114) "noeviction"
 
 
可以在redis.conf配置文件中,设置maxmemory用于表示redis的读/写最大内存,如果该值为0则表示没有限制;
 
maxmemory-policy用于设置回收策略,当内存达到maxmemory限制时,如果不进行回收,redis进程可能会挂掉,maxmemory-policy有6种方式用于回收:
 
  • volatile-lru:(默认值)从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
  • volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
  • volatile-ttl : 从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
  • allkeys-lru : 从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
  • allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
  • noeviction : 禁止驱逐数据,永不过期,返回错误
 
redisObject结果中包括一个lru属性,其中记录了对象最后一次被命令程序访问时的时间,lru属性用于配合实现valatile-ttl和allkeys-lru回收策略使用。
 
在redis中lru算法是一个近似算法,默认情况下,redis会随机挑选maxmemory-samples个键,从中选取一个最近最久未使用的key进行淘汰。
 
在配置文件中可以通过maxmemory-samples的值来设置redis需要检查key的个数,但是检查的越多,耗费的时间也就越久,但是结构越精确(也就是Redis从内存中淘汰的对象未使用的时间也就越久~)。
 
 

Redis运行时内存占用

 
 
info命令中返回memory部分:
 
# Memory
used_memory:895628864
used_memory_human:854.14M
used_memory_rss:939532288
used_memory_peak:912382408
used_memory_peak_human:870.12M
used_memory_lua:36864
mem_fragmentation_ratio:1.05
mem_allocator:jemalloc-3.6.0
 
 
used_memory表示由redis分配器分配的内存,byte为单位;used_memory_human是used_memory的人类可读方式;used_memory_rss是指从操作系统的角度,返回redis已分配的内存总量(常驻集大小),与top,ps等操作系统命令返回一致。
 
如果redis中过期了一定的keys,used_memory会降低,rss不会降低(redis释放的内存,短期内不会返回给操作系统),会产生一定的内存碎片。
 
mem_fragmentation_ratio, 1.05表示内存碎片率(used_memory_rss/used_memory),稍大于1是比较合理的,说明redis没有发生内存交换,但如果内存碎片率超过1.5,就说明redis消耗了实际需要物理内存的150%,其中50%是内存碎片率;若是内存碎片率低于1的话,说明redis内存分配超出了物理内存,操作系统正在进行内存交换,内存交换会引起比较明显的响应延迟。
 
除非你能够保证你的机器总是有一半的空闲内存,否则别使用快照方式持久化数据或者通过执行BGREWRITEAOF压缩aof文件。 redis在执行bgsave时,会进行一次fork,fork后的进程负责将内存中的数据写入磁盘,由于fork采用Copy-On-Write,两个redis进程共享内存中的数据。redis如果有数据更新,则会将对应的共享内存页创建一份副本再更新,当更新操作足够频繁时,共享的内存空间会迅速地副本化,导致物理内存被耗光,系统被迫动用交换空间,从而导致redis服务极不稳定,整个系统堵塞在磁盘io上。
 
而切分slot的结果是导致了其中数据量比较大的节点占用内存是其他两个节点的10倍。
 
关于redis内部的内存优化,可以参考:http://www.infoq.com/cn/articles/tq-redis-memory-usage-optimization-storage
 
 

Redis中的key内存估算

 
除了通过redis info命令宏观地查看其中的所有keys占用内存,以及系统分配内容,还可以借助外部工具来查看
 
 
通过安装该工具来对redis的内存进行分析:
 

1.分析单个key:

 
redis-memory-for-key -s 192.168.1.137 -p 6389 {prod}_brand
Key                    "{prod}_brand"
Bytes                  443636.0
Type                   hash
Encoding                   hashtable
Number of Elements             550
Length of Largest Element          1479
 
 
此时,会输出该key的一些基本信息,type,encoding等,其中我们比较关心的是bytes字段。
 
经过分析发现,对于redis中的值,该分析过程输出的bytes(容量)会比该值(本身的字符串bytes[].length)本身要大,这其中可能要考虑到redis的管理成本,通过infoQ那篇文章也能看到端倪。
 

2.分析整个dump文件,产生memory报告

 
很可惜,我们需要的memory report并没有生成出来,报错了...
 
rdb -c memory dump.6389.rdb > memory.csv
Traceback (most recent call last):
  File "/usr/local/bin/rdb", line 9, in <module>
    load_entry_point('rdbtools==0.1.7', 'console_scripts', 'rdb')()
  File "/Library/Python/2.7/site-packages/rdbtools-0.1.7-py2.7.egg/rdbtools/cli/rdb.py", line 72, in main
    parser.parse(dump_file)
  File "/Library/Python/2.7/site-packages/rdbtools-0.1.7-py2.7.egg/rdbtools/parser.py", line 293, in parse
    self.parse_fd(open(filename, "rb"))
  File "/Library/Python/2.7/site-packages/rdbtools-0.1.7-py2.7.egg/rdbtools/parser.py", line 337, in parse_fd
    self._callback.end_database(db_number)
  File "/Library/Python/2.7/site-packages/rdbtools-0.1.7-py2.7.egg/rdbtools/memprofiler.py", line 150, in end_database
    self._stream.next_record(record)
  File "/Library/Python/2.7/site-packages/rdbtools-0.1.7-py2.7.egg/rdbtools/memprofiler.py", line 90, in next_record
    self._out.write("%d,%s,%s,%d,%s,%d,%d\n" % (record.database, record.type, encode_key(record.key),
  File "/Library/Python/2.7/site-packages/rdbtools-0.1.7-py2.7.egg/rdbtools/callbacks.py", line 91, in encode_key
    return _encode(s, quote_numbers=True)
  File "/Library/Python/2.7/site-packages/rdbtools-0.1.7-py2.7.egg/rdbtools/callbacks.py", line 88, in _encode
    return _encode_basestring_ascii(s)
  File "/Library/Python/2.7/site-packages/rdbtools-0.1.7-py2.7.egg/rdbtools/callbacks.py", line 69, in _encode_basestring_ascii
    return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"'
TypeError: expected string or buffer
 
 
 
如果dump文件比较大,会造成分析的过程比较长。
 

3.将dump文件转换成json

 
如果单独看dump文件,使用head命令时,文件属于二进制格式,并不能以可以看的方式显示:
 
REDIS0006�$DFDF3DB1-5371-4644-BC12-B784DE6C6F9AppStorepriceStock_spec_106488�28{"price":3299,"marketP�
                                                                                                      850,"stock":         fixS�
                                                                                                                             0}$86A586E8-30A3-4{"brandId":97,�F1366AppStore{prod}_base_info_25560�C�E�
               Name":"TOD'S","category@#10hannel":4
                                                    ustomsR "":0.@
editorIntro D一双美丽的高跟鞋就像 位拥有魔法 #仙女,在脚尖轻  ,点@��能让穿上它 5  5人变得更性感迷 !借助那些精@� h�� 8 z力 Y来 V自己成为镁光灯下 )焦 �吧。!gender �
  
 
但可以将其转换为json,下面就是将符合正则条件格式的key转换为json:
 
rdb --command json --key "{prod}_*" dump.6389.rdb  > temp
  
当然还有一些其他参数可以使用,比如db, type(键值类型)。
 
[{
"{prod}_base_info_25560":"{\"brandId\":97,\"brandName\":\"TOD'S\",\"categoryId\":10,\"channel\":4,\"customsRate\":0.10,\"editorIntro\":\"\u4e00\u53cc\u7f8e\u4e3d\u7684\u9ad8\u8ddf\u978b\u5c31\u50cf\u4e00\u4f4d\u62e5\u6709\u9b54\u6cd5\u7684\u4ed9\u5973\uff0c\u5728\u811a\u5c16\u8f7b\u8f7b\u4e00\u70b9\uff0c\u5c31\u80fd\u8ba9\u7a7f\u4e0a\u5b83\u7684\u7684\u5973\u4eba\u53d8\u5f97\u66f4\u6027\u611f\u8ff7\u4eba\uff01\u501f\u52a9\u90a3\u4e9b\u7cbe\u7f8e\u4ed9\u5c65\u7684\u9b54\u529b\uff0c\u6765\u8ba9\u81ea\u5df1\u6210\u4e3a\u9541\u5149\u706f\u4e0b\u7684\u7126\u70b9\u5427\u3002\",\"gender\":0,\"goodsId\":19917,\"imageSource\":\"http://pic2.zhenimg.com/upload2/45/0c/450c490c4bdb85a72eac185ab05b591e.jpg\",\"isSpecial\":0,\"isStop\":0,\"mSmall\":\"http://pic2.zhenimg.com/upload2/45/0c/m_small_450c490c4bdb85a72eac185ab05b591e.jpg\",\"marketPrice\":5600,\"price\":1680,\"productAd\":\"\",\"productCode\":\"HY XXW0LK08780G23 740A\",\"productDetail\":\"\",\"productId\":25560,\"productImage\":\"[\\\"http://pic2.zhenimg.com/upload2/45/0c/450c490c4bdb85a72eac185ab05b591e.jpg\\\",\\\"http://pic2.zhenimg.com/upload2/fa/b9/fab98f7eb6261d90884857d771f1119b.jpg\\\",\\\"http://pic2.zhenimg.com/upload2/8a/9c/8a9c5b5dea7907817eb4721a46fbec42.jpg\\\",\\\"http://pic2.zhenimg.com/upload2/14/b4/14b4c0b6ce75541fa30b364e3788f52a.jpg\\\",\\\"http://pic2.zhenimg.com/upload2/ef/b3/efb3b3b9a14b8215bdc52b33c08c5377.jpg\\\",\\\"http://pic2.zhenimg.com/upload2/43/09/4309cafb27158298add464e75d5c547e.jpg\\\",\\\"http://pic2.zhenimg.com/upload2/5e/d1/5ed141b0efb6b4e6372d6323cb715ff7.jpg\\\",\\\"http://pic2.zhenimg.com/upload2/2e/44/2e44baef1e86b86134c02ef077d40578.jpg\\\"]\",\"productName\":\"TOD'S/\u6258\u5fb7\u65af \u9ed1\u8272/\u7d2b\u7ea2\u8272 \u5c0f\u725b\u76ae \u5973\u58eb\u9ad8\u8ddf\u978b HY XXW0LK08780G23 740A\",\"providerId\":18,\"providerStorageId\":1,\"skuIds\":[\"38455\",\"38456\",\"38457\"],\"status\":0,\"urlId\":79052250}",
 
 
如果将其转换成json,原有的dump文件大概270M,json文件增长为700M左右(且我们只转换了其中的一部分)。
 
 

如何修改默认的分槽策略

 
在制定HASH Tag方案后,不可避免地使得有些slot key会集中到一台/几台服务器上,此时或许我们可以将一些占用空间较大的slot比较集中的server释放一下压力,将其slot转移至新增的服务器上。
 
在一个redis集群中,可以通过cluster info查看当前集群状态:
 
> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:35
cluster_my_epoch:35
cluster_stats_messages_sent:7324
cluster_stats_messages_received:7324
 
 
通过cluster nodes命令查看当前集群机器分布情况:
 
d08dc883ee4fcb90c4bb47992ee03e6474398324 192.168.1.137:6390 master - 0 1471661565059 33 connected 5641-11040
5974ed7dd81c112d9a2354a0a985995913b4702c 192.168.1.137:6389 slave ffb4db4e1ced0f91ea66cd2335f7e4eadc29fd56 0 1471661563556 35 connected
532e58842d001f8097fadc325bdb5541b788a360 192.168.1.138:6389 master - 0 1471661564058 29 connected 11041-16383
ffb4db4e1ced0f91ea66cd2335f7e4eadc29fd56 192.168.1.138:6390 myself,master - 0 0 35 connected 0-5640
c69b521a30336caf8bce078047cf9bb5f37363ee 192.168.1.137:6388 slave 532e58842d001f8097fadc325bdb5541b788a360 0 1471661564058 29 connected
aa52c7810e499d042e94e0aa4bc28c57a1da74e3 192.168.1.138:6388 slave d08dc883ee4fcb90c4bb47992ee03e6474398324 0 1471661565562 33 connected
 
 
 

技术解决

 
从技术上考虑,解决该问题的方法有几种:
 

减少redis的单个元素值大小

 
改用其他类型的解决方案,各种序列化方案的对比表现:https://github.com/eishay/jvm-serializers/wiki,体现在 序列化/反序列化的速度,以及序列化后占用空间大小。我们当前使用fastjson,可以考虑使用更加高效的protostuff来代替。
 

垂直扩展,增加单个redis服务可用内存

 
但绝不能随意加,估算出大概需要的内存量并进行合理规划
 

水平扩展,加机器

 
重新切分slot,将占用内存较大的slot单独切分出去,集群中对slot进行相关操作的命令主要有:
 
 
/集群(cluster)
CLUSTER INFO 打印集群的信息
CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相关信息。
 
//节点(node)
CLUSTER MEET <ip> <port> 将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
CLUSTER FORGET <node_id> 从集群中移除 node_id 指定的节点。
CLUSTER REPLICATE <node_id> 将当前节点设置为 node_id 指定的节点的从节点。
CLUSTER SAVECONFIG 将节点的配置文件保存到硬盘里面。
 
//槽(slot)
CLUSTER ADDSLOTS <slot> [slot ...] 将一个或多个槽(slot)指派(assign)给当前节点。
CLUSTER DELSLOTS <slot> [slot ...] 移除一个或多个槽对当前节点的指派。
CLUSTER FLUSHSLOTS 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
CLUSTER SETSLOT <slot> NODE <node_id> 将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。
CLUSTER SETSLOT <slot> MIGRATING <node_id> 将本节点的槽 slot 迁移到 node_id 指定的节点中。
CLUSTER SETSLOT <slot> IMPORTING <node_id> 从 node_id 指定的节点中导入槽 slot 到本节点。
CLUSTER SETSLOT <slot> STABLE 取消对槽 slot 的导入(import)或者迁移(migrate)。
 
//键 (key)
CLUSTER KEYSLOT <key> 计算键 key 应该被放置在哪个槽上。
CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的键值对数量。
CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 个 slot 槽中的键。
 
 
 
通过cluster keyslot和countkeysinslot查看集中的slot占用的总数量:
 
> cluster keyslot {prod}
(integer) 811
> cluster countkeysinslot 811
(integer) 361528
 
 
将指定的keyslot迁移到对应的节点上去:
 
cluster setslot 4781 migrating d08dc883ee4fcb90c4bb47992ee03e6474398324
  
此时节点的状态已经改变:
 
cluster nodes
d08dc883ee4fcb90c4bb47992ee03e6474398324 192.168.1.137:6390 master - 0 1471663968706 33 connected 5641-11040
5974ed7dd81c112d9a2354a0a985995913b4702c 192.168.1.137:6389 slave ffb4db4e1ced0f91ea66cd2335f7e4eadc29fd56 0 1471663969206 35 connected
532e58842d001f8097fadc325bdb5541b788a360 192.168.1.138:6389 master - 0 1471663968706 29 connected 11041-16383
ffb4db4e1ced0f91ea66cd2335f7e4eadc29fd56 192.168.1.138:6390 myself,master - 0 0 35 connected 0-5640 [4781->-d08dc883ee4fcb90c4bb47992ee03e6474398324]
c69b521a30336caf8bce078047cf9bb5f37363ee 192.168.1.137:6388 slave 532e58842d001f8097fadc325bdb5541b788a360 0 1471663970709 29 connected
aa52c7810e499d042e94e0aa4bc28c57a1da74e3 192.168.1.138:6388 slave d08dc883ee4fcb90c4bb47992ee03e6474398324 0 1471663970209 33 connected
 
 
此种方法是否有效也亟待在生产环境中试验。
 

由分槽内存占用过大导致的另一个问题
 
我们在由于内存占用过高导致的进程down掉的redis节点上,执行批量删除操作时,提示下面的错误:
 
> redis-cli -c -p 6390 keys "\{prod\}*" | xargs redis-cli -c -p 6390 del
 
(error) MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
(error) MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
(error) MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
(error) MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
(error) MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
(error) MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
(error) MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
(error) MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
(error) MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
  
经过一番查询,找出问题所在,是由于redis意外挂掉导致快照停止导致的,查看redis_last_bgsave_status为err而不是ok,通过状态可以证实这一点,需要关闭属性 stop-writes-on-bgsave-error ,注意要关闭master节点上的该属性而不是 slave节点上的,并在master节点上执行删除操作。
 
config set stop-writes-on-bgsave-error no
 
 
记得在执行完成后,将其重置为yes,如果conf文件中没有设置,则下次重启后仍然会设置为默认值yes。 
分享到:
评论

相关推荐

    Laravel/Lumen 使用 Redis队列

    如果使用 Redis Cluster(集群),队列名称必须包含 key hash tag,以确保给定队列对应的所有 Redis keys 都存放到同一个 hash slot。 三、驱动预备知识 使用 database 队列驱动需要数据表保存任务信息,例如失败...

    老大看见你这样用Redis会揍你

    使用 Hash Tag 技术可以确保所有键映射到同一个槽,从而避免这个问题。 7. **`ZREM` 批量删除缓存**: 危险指数:高 大量的 `ZREM` 操作可能导致 Redis 被阻塞。应分批删除,以减小对 Redis 性能的影响。 8. **`...

    Redis集群部署

    Redis集群采用了与一致性哈希不同的分片机制,主要基于哈希槽(hash slot)的概念。 - **哈希槽数量**:Redis集群定义了16384个哈希槽。 - **哈希槽计算规则**:通过计算键(key)的CRC16校验码后对其16384取模得到键...

    redis 与网站架构

    同样,问题作者的信息也可以以同样的方式存储为另一个Hash。这样,在需要获取这些问题信息时,只需要通过简单的命令就可以一次性获取所有需要的数据,而无需执行多次数据库查询。 示例代码: ```php $user = array...

    redis单机部署.pdf

    - 对于 macOS 和 Linux 用户:[https://github.com/uglide/RedisDesktopManager/releases/tag/0.8.8](https://github.com/uglide/RedisDesktopManager/releases/tag/0.8.8) - 对于 Windows 用户:...

    ServiceStack.Redis

    3. **Redis数据类型**:Redis支持五种基本数据类型:String(字符串)、Hash(哈希)、List(列表)、Set(集合)和Sorted Set(有序集合)。ServiceStack.Redis提供了与这些数据类型对应的API,例如`GetString`, `...

    Redis介绍加实践

    然而,它也存在一些缺点,如查询功能相对简单、数据单个值大小有限制(最大1GB)、依赖于内存硬件,以及在数据持久化方面可能由于配置不当导致效率问题。 在应用场景方面,Redis可以在以下场景中发挥作用: 1. ...

    Redis 35 道面试题及答案.docx

    Redis 的特点是整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据 flush 到硬盘上进行保存。因为是纯内存操作,Redis 的性能非常出色,每秒可以处理超过 10 万次读写操作,是已知性能最快的 Key-...

    2023年Redis面试题及答案.docx

    Redis 支持保留多种数据构造,如 List、Set、Sorted Set、Hash 等,且单个 value 的最大限制是 1GB,不像 Memcached 只能保留 1MB 的数据。因此 Redis 可以用来实现诸多有用功能,比方说用 List 来做 FIFO 双向链表...

    Java高级面试题.doc

    Redis 使用单线程模型,数据顺序提交,Redis 支持主从模式,Memcache 只支持一致性 Hash 做分布式;Redis 支持数据落地,RDB 定时快照和 AOF 实时记录操作命令的日志备份,Memcache 不支持;Redis 数据类型丰富,有 ...

    亿级流量电商详情页系统实战-缓存架构+高可用服务架构+微服务架构

    7、Redis集群的批量数据查询性能优化:对于分布式的Redis集群,数据在多个实例中分布式存储,如果要优化大批量数据的批量查询性能,就需要采用hash tag分片路由+mget单分批大批量读取的优化设计。 8、高可用架构...

    2017年尚学堂Java培训课程大纲.docx

    - **Redis支持的数据结构**:学习Redis支持的各种数据结构,如String、List、Set、Hash等。 - **常用Redis命令**:掌握Redis的基本命令,如操作字符串、列表、集合、映射、有序集合等。 - **Java程序访问Redis数据库...

    python入门到高级全栈工程师培训 第3期 附课件代码

    06 百分号字符串拼接 07 format字符串格式化 08 数学意义的函数与python中的函数 09 为何要有函数 10 函数返回值 11 可变长参数 第15章 01 上节课复习 02 全局变量与局部变量 03 风湿理论之函数即变量 04 函数递归...

    最新Python3.5零基础+高级+完整项目(28周全)培训视频学习资料

    Redis hash操作 Redis 集合set 和有序集合操作 Redis 集合操作补充 Redis 发布订阅及本节作业 第12周 上节回顾 数据库介绍 mysql基本使用 mysql数据类型与创建表 mysql 增删改查 mysql 外键关联 mysql 连接查询 ...

    PHP设计

    这可能涉及使用高效的算法,减少数据库查询,使用缓存技术(如Memcached或Redis),以及利用OPCache来加速代码执行。 7. **安全性**:PHP设计应始终注重安全性,包括防止SQL注入、XSS攻击,以及使用HTTPS来保护传输...

    数据库管理系统MySql(JSP版).rar_jsp mysql 系统_jsp管理系统_mysql jsp

    - MySQL的索引类型包括B-Tree、Hash、R-Tree和Full-text,它们对查询性能有着显著影响。 3. **JSP与MySQL的连接**: - JDBC(Java Database Connectivity)是Java与数据库交互的标准接口,JSP通过JDBC驱动程序...

    java开源包1

    Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以直接在你的网页里面显示搜查的结果。 github-java-api github-java-api 是 Github 网站 API 的 Java 语言...

    java开源包11

    Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以直接在你的网页里面显示搜查的结果。 github-java-api github-java-api 是 Github 网站 API 的 Java 语言...

    java开源包2

    Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以直接在你的网页里面显示搜查的结果。 github-java-api github-java-api 是 Github 网站 API 的 Java 语言...

Global site tag (gtag.js) - Google Analytics